
#include "sgks_mdi.h"
#include "mdi_version.h"


#ifdef DEBUG
#define DEBUGMASK(bit)       (1 << (bit))
#define MASK_ERROR           DEBUGMASK(0)
#define MASK_WARN            DEBUGMASK(1)
#define MASK_INIT            DEBUGMASK(2)
#define MASK_FUNCTION        DEBUGMASK(3)
#define MASK_IOCTL           DEBUGMASK(4)
#define MASK_THREAD          DEBUGMASK(5)
#define MASK_INFO            DEBUGMASK(6)
#define MASK_VENC            DEBUGMASK(7)

DBGPARAM dpCurSettings =
{
    "MDI",
    {
        "Errors", "Warnings", "Init", "Function",
        "Ioctl", "THREAD", "", "",
        "", "", "", "",
        "", "", "", "",
    },
    MASK_ERROR | MASK_WARN | MASK_INIT | MASK_INFO | MASK_VENC /*| MASK_THREAD*/,
};

#define ZONE_ERROR           DEBUGZONE(0)
#define ZONE_WARN            DEBUGZONE(1)
#define ZONE_INIT            DEBUGZONE(2)
#define ZONE_FUNCTION        DEBUGZONE(3)
#define ZONE_IOCTL           DEBUGZONE(4)
#define ZONE_THREAD          DEBUGZONE(5)
#define ZONE_INFO            DEBUGZONE(6)
#define ZONE_VENC            DEBUGZONE(7)
#endif

#define MAX_ENCODE_STREAMS_NUM      4
static const char *sgks_mdi_name = "sgks_mdi";
static int sgks_mdi_major = 243;
static int sgks_mdi_minor = 0;
static struct cdev sgks_mdi_cdev;
static sgks_mdi_encode_info_s g_enc_info;
static u32 pre_pic_total = 0;

static DEFINE_MUTEX(dsplog_mutex);
static DEFINE_MUTEX(sgks_mdi_sendcmd_mutex);
static DEFINE_MUTEX(sgks_mdi_mmap_mutex);


static int sgks_mdi_osd_register_to_framebuffer(sgks_mdi_osdVoInfoToFb_s *info);


static sgks_mdi_manager_s g_mdi_manager;

static void sgks_mdi_cmd_lock(void)
{
    //printk("sgks_mdi_cmd_lock\n");
    mutex_lock(&sgks_mdi_sendcmd_mutex);
}

static void sgks_mdi_cmd_unlock(void)
{
    //printk("sgks_mdi_cmd_unlock\n");
    mutex_unlock(&sgks_mdi_sendcmd_mutex);
}

static void sgks_mdi_mmap_lock(void)
{
    //printk("sgks_mdi_mmap_lock\n");
    mutex_lock(&sgks_mdi_mmap_mutex);
}

static void sgks_mdi_mmap_unlock(void)
{
    //printk("sgks_mdi_mmap_unlock\n");
    mutex_unlock(&sgks_mdi_mmap_mutex);
}


static int sgks_mdi_sendDefaultcmd(char *dsp_cmd, int dsp_cmd_size)
{

    sgks_cmd_info_s *mdi_default_cmd_buff  = &g_mdi_manager.dsp_buff.cmd_buff.default_cmd_buffer;

    if (mdi_default_cmd_buff->buffer_addr == NULL)
    {
        return SGKS_FAIL;
    }

    sgks_dsp_cmd_header_s *cmdq_header = &mdi_default_cmd_buff->cmd_head;
    u8 *ptr = NULL;


    if(cmdq_header->num_cmd >= SGKS_MDI_MAX_DEFAULT_CMD_NUM)
    {
        mdi_error("default cmd number err!\n");
        return SGKS_OPERATION_ERR_DEFCMD;
    }



    ptr = (u8 *)mdi_default_cmd_buff->buffer_addr + sizeof(sgks_dsp_cmd_header_s) + cmdq_header->num_cmd * SGKS_MDI_CMD_SIZE;

	//printk("send defautl cmd ptr 0x%x\n",ptr);
	
    memcpy(ptr, dsp_cmd, dsp_cmd_size);
    memset(ptr + dsp_cmd_size, 0, SGKS_MDI_CMD_SIZE - dsp_cmd_size);

    cmdq_header->num_cmd++;


    return SGKS_SUCCESS;

}


static int sgks_mdi_sendNormalcmd(char *dsp_cmd, int dsp_cmd_size)
{

    //printk("sgks_mdi_sendNormalcmd\n");

    unsigned long flags;
    sgks_dsp_cmd_header_s *mdi_cmdq_header     = NULL;
    sgks_cmd_info_s *mdi_normal			     = NULL;
    u8 *mdi_normal_buff					     = NULL;
    u8 *ptr 									 = NULL;

    mdi_normal 							= &g_mdi_manager.dsp_buff.cmd_buff.normal_cmd_buffer;
    mdi_normal_buff			  			= g_mdi_manager.dsp_buff.cmd_buff.normal_cmd_buffer.buffer_temp_area;
    mdi_cmdq_header           			= &g_mdi_manager.dsp_buff.cmd_buff.normal_cmd_buffer.cmd_head;
    int ret = 0;

    while(1)
    {

        local_irq_save(flags);

        if (mdi_cmdq_header->num_cmd == 0)
        {
            //printk("[send NormalA cmd] wait dsp send ok\n");
            break;
        }

        g_mdi_manager.dsp_compl.cmd_avail_compl_wait_count++;

        local_irq_restore(flags);

        WAIT_FOR_COMPL_TIMEOUT("cmd_avail_compl", &g_mdi_manager.dsp_compl.cmd_avail_compl, 10 * HZ, &ret);
        if (ret != SGKS_SUCCESS)
        {
            local_irq_restore(flags);
            return SGKS_FAIL;
        }

        msleep(10);

    }

    if (g_mdi_manager.dsp_buff.cmd_buff.cmd_mode == SGKS_MDI_CMD_MODE_BLOCK_LOADING)
    {

        ptr = mdi_normal_buff;

        memcpy(ptr, dsp_cmd, dsp_cmd_size);

        mdi_cmdq_header->num_cmd = (dsp_cmd_size / SGKS_DSP_CMD_SIZE);

        //printk("NormalA block top [%d]\n",mdi_cmdq_header->num_cmd);

    }
    else
    {

        ptr = mdi_normal_buff + mdi_cmdq_header->num_cmd * SGKS_DSP_CMD_SIZE;

        memcpy(ptr, dsp_cmd, dsp_cmd_size);

        if (dsp_cmd_size < SGKS_DSP_CMD_SIZE)
        {
            //printk("NormalA one\n");
            memset(ptr + dsp_cmd_size, 0, SGKS_DSP_CMD_SIZE - dsp_cmd_size);
            mdi_cmdq_header->num_cmd++;
        }
        else
        {
           //printk("NormalA Multiple\n");
            mdi_cmdq_header->num_cmd += (dsp_cmd_size / SGKS_DSP_CMD_SIZE);
        }
    }

    local_irq_restore(flags);

#if 0
    printk("[send NormalA cmd] mdi_cmdq_header->num_cmd %d, cmd code 0x%x, curr cmd size %d\n"
           ,mdi_cmdq_header->num_cmd
           ,*(u32*)dsp_cmd
           ,dsp_cmd_size);
#endif
    return SGKS_SUCCESS;

}



static void sgks_mdi_sendBlockOccupyCmd()
{
    unsigned long flags;
    sgks_dsp_cmd_header_s *mdi_occupy_cmdq_header     	= NULL;
    sgks_cmd_info_s *mdi_occupy				     		= NULL;
    u8 *mdi_occupy_buff						     		= NULL;
    int i = 0;

    mdi_occupy 												= &g_mdi_manager.dsp_buff.cmd_buff.block_occupy_buffer;
    mdi_occupy_buff			  								= g_mdi_manager.dsp_buff.cmd_buff.block_occupy_buffer.buffer_temp_area;
    mdi_occupy_cmdq_header           						= &g_mdi_manager.dsp_buff.cmd_buff.block_occupy_buffer.cmd_head;


    if (mdi_occupy_cmdq_header->num_cmd > 0)
    {
        printk("[send NormalA for BlockOccupy] mdi_occupy_cmdq_header->num_cmd %d\n",mdi_occupy_cmdq_header->num_cmd);
        sgks_mdi_sendNormalcmd(mdi_occupy_buff, mdi_occupy_cmdq_header->num_cmd * SGKS_DSP_CMD_SIZE);
        mdi_occupy_cmdq_header->num_cmd = 0;
    }

    return ;

}


static int sgks_mdi_saveBlockOccupyCmd(char *dsp_cmd, int dsp_cmd_size)
{
    unsigned long flags;
    sgks_dsp_cmd_header_s *mdi_occupy_cmdq_header     	= NULL;
    sgks_cmd_info_s *mdi_occupy				     		= NULL;
    u8 *mdi_occupy_buff						     		= NULL;
    u8 *ptr 									 			= NULL;

    mdi_occupy 									= &g_mdi_manager.dsp_buff.cmd_buff.block_occupy_buffer;
    mdi_occupy_buff			  					= g_mdi_manager.dsp_buff.cmd_buff.block_occupy_buffer.buffer_temp_area;
    mdi_occupy_cmdq_header           			= &g_mdi_manager.dsp_buff.cmd_buff.block_occupy_buffer.cmd_head;

    if (mdi_occupy_cmdq_header->num_cmd > (SGKS_DSP_MAX_CMD_NUM - 6))/*Reserve max block cmd num*/
    {
        printk("sgks_mdi_saveBlockOccupyCmd err, cmd num %d\n",mdi_occupy_cmdq_header->num_cmd);
        return SGKS_FAIL;
    }

    printk("[save blockOccupy] mdi_cmdq_header->num_cmd %d, cmd code 0x%x\n",mdi_occupy_cmdq_header->num_cmd, *(u32 *)dsp_cmd);

    ptr = mdi_occupy_buff + mdi_occupy_cmdq_header->num_cmd * SGKS_DSP_CMD_SIZE;
    memcpy(ptr, dsp_cmd, dsp_cmd_size);
    memset(ptr + dsp_cmd_size, 0, SGKS_DSP_CMD_SIZE - dsp_cmd_size);
    mdi_occupy_cmdq_header->num_cmd++;

	return 0;
	
}


static int sgks_mdi_saveBlockcmd(char *dsp_cmd, int dsp_cmd_size)
{

    unsigned long flags;
    sgks_dsp_cmd_header_s *mdi_cmdq_header     = NULL;
    sgks_cmd_info_s *mdi_block				     = NULL;
    u8 *mdi_block_buff						     = NULL;
    u8 *ptr 									 = NULL;

    u32 cmd_code = *(u32*)dsp_cmd;

	if (cmd_code >= 0x2000 && cmd_code <=0x2fff)
	{
		sgks_mdi_saveBlockOccupyCmd(dsp_cmd, dsp_cmd_size);
		return 0;
	}
	
    mdi_block 							= &g_mdi_manager.dsp_buff.cmd_buff.block_cmd_buffer;
    mdi_block_buff			  			= g_mdi_manager.dsp_buff.cmd_buff.block_cmd_buffer.buffer_temp_area;
    mdi_cmdq_header           			= &g_mdi_manager.dsp_buff.cmd_buff.block_cmd_buffer.cmd_head;
 
    if (mdi_cmdq_header->num_cmd > SGKS_DSP_MAX_CMD_NUM)
    {
        printk("sgks_mdi_saveBlockcmd err\n");
        return SGKS_FAIL;
    }

    printk("[save blockcmd] mdi_cmdq_header->num_cmd %d, cmd code 0x%x\n",mdi_cmdq_header->num_cmd, *(u32 *)dsp_cmd);

    ptr = mdi_block_buff + mdi_cmdq_header->num_cmd * SGKS_DSP_CMD_SIZE;
    memcpy(ptr, dsp_cmd, dsp_cmd_size);
    memset(ptr + dsp_cmd_size, 0, SGKS_DSP_CMD_SIZE - dsp_cmd_size);
    mdi_cmdq_header->num_cmd++;

    return SGKS_SUCCESS;

}

static int sgks_mdi_sendBlockcmd()
{

    //printk("sgks_mdi_sendBlockcmd\n");

    unsigned long flags;
    sgks_dsp_cmd_header_s *mdi_block_cmdq_header 	= NULL;
    sgks_cmd_info_s *mdi_block				     	= NULL;
    u8 *mdi_block_buff						     	= NULL;
    int i = 0;

    mdi_block 										= &g_mdi_manager.dsp_buff.cmd_buff.block_cmd_buffer;
    mdi_block_buff			  						= g_mdi_manager.dsp_buff.cmd_buff.block_cmd_buffer.buffer_temp_area;
    mdi_block_cmdq_header      						= &g_mdi_manager.dsp_buff.cmd_buff.block_cmd_buffer.cmd_head;

    if (mdi_block_cmdq_header->num_cmd > 0)
    {
        printk("[send NormalA for blockcmd] mdi_block_cmdq_header->num_cmd %d \n", mdi_block_cmdq_header->num_cmd);
        sgks_mdi_sendNormalcmd(mdi_block_buff, mdi_block_cmdq_header->num_cmd * SGKS_DSP_CMD_SIZE);
        mdi_block_cmdq_header->num_cmd = 0;
    }

    return SGKS_SUCCESS;

}



static int sgks_mdi_WaitSendToDspNormalCmdBuff()
{

    //printk("sgks_mdi_WaitSendToDspNormalcmd start\n");

 	unsigned long flags;
    int ret 											= 0;
    sgks_dsp_cmd_header_s   *mdi_normal_cmdq_header 	= &g_mdi_manager.dsp_buff.cmd_buff.normal_cmd_buffer.cmd_head;

    while(1)
    {

        msleep(1);

        local_irq_save(flags);

        if(mdi_normal_cmdq_header->num_cmd == 0)
        {

            break;
        }


        g_mdi_manager.dsp_compl.cmd_avail_compl_wait_count++;

        local_irq_restore(flags);


        WAIT_FOR_COMPL_TIMEOUT("cmd_avail_compl", &g_mdi_manager.dsp_compl.cmd_avail_compl, 10 * HZ, &ret);
        if (ret != SGKS_SUCCESS)
        {
            local_irq_restore(flags);
            return SGKS_FAIL;
        }

    }

    //printk("sgks_mdi_WaitSendToDspNormalcmd end \n");


    return SGKS_SUCCESS;

}





static int sgks_mdi_sendVdecNormalcmd(char *dsp_cmd, int dsp_cmd_size)
{

    // printk("  vdec sgks_mdi_sendNormalcmd\n");

    unsigned long flags;
    sgks_dsp_cmd_header_s *mdi_cmdq_header     = NULL;
    sgks_cmd_info_s *mdi_normal			     = NULL;
    u8 *mdi_normal_buff					     = NULL;
    u8 *ptr 									 = NULL;

    mdi_normal 							= &g_mdi_manager.dsp_buff.cmd_buff.normal_cmd_buffer;
    mdi_normal_buff			  			= g_mdi_manager.dsp_buff.cmd_buff.normal_cmd_buffer.buffer_temp_area;
    mdi_cmdq_header           			= &g_mdi_manager.dsp_buff.cmd_buff.normal_cmd_buffer.cmd_head;

    while(1)
    {
        if(mdi_cmdq_header->num_cmd < SGKS_DSP_MAX_CMD_NUM)
            break;

        msleep(1);
    }

    local_irq_save(flags);
    ptr = mdi_normal_buff + mdi_cmdq_header->num_cmd * SGKS_DSP_CMD_SIZE;
    memcpy(ptr, dsp_cmd, dsp_cmd_size);
    memset(ptr + dsp_cmd_size, 0, SGKS_DSP_CMD_SIZE - dsp_cmd_size);
    mdi_cmdq_header->num_cmd++;
    local_irq_restore(flags);
    printk("vdec mdi_cmdq_header->num_cmd %d, curr cmd size %d, code 0x%x\n",mdi_cmdq_header->num_cmd,dsp_cmd_size,*(u32*)dsp_cmd);



    return SGKS_SUCCESS;

}



static inline int sgks_mdi_ioc_read_reg(sgks_mdi_reg_rw_s *data, u8 pri_flag)
{
    sgks_mdi_reg_rw_s *reginfo = data;
    unsigned long *reg_map     = NULL;
    int i = 0;
    u32 val;

    for (i=0; i<reginfo->reg_num; i++)
    {

        if (reginfo->reg_info[i].addr_type == SGKS_MDI_REG_ADDR_TYPE_VIR)
        {
            reginfo->reg_info[i].val = sgks_readl(reginfo->reg_info[i].addr);

            if (pri_flag)
            {
                printk("[read reg vir] <0x%x> = <0x%x>\n",reginfo->reg_info[i].addr, reginfo->reg_info[i].val);
            }

        }
        else if (reginfo->reg_info[i].addr_type == SGKS_MDI_REG_ADDR_TYPE_PHY)
        {

            reg_map = (unsigned long *)ioremap(reginfo->reg_info[i].addr, 4);

            reginfo->reg_info[i].val = *reg_map;

            if (pri_flag)
            {
                printk("[read reg phy] <0x%x> = <0x%x>\n",reginfo->reg_info[i].addr,reginfo->reg_info[i].val);
            }

            iounmap(reginfo->reg_info[i].addr);

        }




    }

    return SGKS_SUCCESS;

}


static inline int sgks_mdi_ioc_clean_cache(sgks_mdi_opt_d_cache_e 	cache_type, u8 *start, unsigned long size)
{
    if(start == NULL)
    {
       DEBUGMSG(ZONE_ERROR, ("%s: Error: start is NULL!\n", __FUNCTION__));
       return SGKS_FAIL;
    }
    
    unsigned long offset = (unsigned long)start & (CACHE_LINE_SIZE - 1);

	start -= offset;
    size  += offset;
	
    if (cache_type ==SGKS_OPT_D_CACHE_CLAEN)
    {
        clean_d_cache(start, size);
    }
    else if (cache_type ==SGKS_OPT_D_CACHE_INV)
    {
		invalidate_d_cache(start, size);
    }
    else
    {
		printk("clean_cache err!\n");
		return SGKS_FAIL;
    }

	return SGKS_SUCCESS;
	
}


static u8 *G_buffer = NULL;
static u8 *G_buffer_end;
static u8 *G_buffer_read_ptr;
static u8 *G_buffer_write_ptr;
static u32 G_buf_fullness = 0;//  read data  
#define SGKS_DSP_LOG_SIZE 0x10000

sgks_cap_dsp_log_file_s g_log_serv;
static u8  g_log_pthread = 0;
sgks_icore_printf_s *dsp_log_blk;

struct file *g_filep = NULL;
mm_segment_t g_fs;
loff_t g_pos;
typedef void (* HIGH_RES_TIMER_CALLBACK)(void);

#define MS_TO_NS(x)    ((u32)(((u32)x) * (u32)1000000L))
static struct hrtimer hr_timer;
static ktime_t ktime;
#define TURBO_CMD_DELAY        8L
static HIGH_RES_TIMER_CALLBACK s_pCallback_high_res = NULL;
#define SESSION_ID_INDEX_SIZE         (16)
static u32 g_stream_session_id[MAX_ENCODE_STREAMS_NUM][SESSION_ID_INDEX_SIZE];
static int g_stream_session_index[MAX_ENCODE_STREAMS_NUM]; //index value is 0~15


static void sgks_mdi_timer_test()
{
    printk("sgks_mdi_timer_test\n");
}


static enum hrtimer_restart hrtimer_callback(struct hrtimer *timer)
{

    if(s_pCallback_high_res)
    {
        s_pCallback_high_res();
    }

    return HRTIMER_NORESTART;
}


int sgks_mdi_InitHighresTimer(void *pcallback)
{

    HIGH_RES_TIMER_CALLBACK ptimercb = (HIGH_RES_TIMER_CALLBACK)pcallback;

    if(!ptimercb)
    {
        return -1;
    }

    printk("Init software HR timer for DSP communication\n");
    s_pCallback_high_res = ptimercb;
    highres_timer_init(&hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    hr_timer.function = &hrtimer_callback;
    return 0;
}


int sgks_mdi_StartHighresTimer(u32 ms_to_timeout)
{
    ktime = ktime_set(0, MS_TO_NS(ms_to_timeout));
    return highres_timer_start(&hr_timer, ktime, HRTIMER_MODE_REL);
}

static int log_file_num = 0;
static int log_file_size = 0;
#define LOG_FILE_LEN (20*1024*1024)

static void sgks_mdi_log_WriteFile(char *data, int size)
{

    char file_name[128] = {0};

    if (g_filep == NULL || log_file_size >= LOG_FILE_LEN )
    {

        if (log_file_size >= LOG_FILE_LEN)
        {
            filp_close(g_filep, 0);
            log_file_size = 0;
        }

        sprintf(file_name, "%s-%d",g_log_serv.log_file_path,log_file_num++);

        g_filep = filp_open(file_name, O_CREAT | O_RDWR, 777);

        if(IS_ERR(g_filep))
        {
            return -1;
        }

        printk("new log file %s\n",file_name);

        g_fs = get_fs();

        set_fs(KERNEL_DS);

        g_pos = 0;

    }

    vfs_write(g_filep, data, size, &g_pos);
    log_file_size += size;

    return ;
}


static int sgks_mdi_log_ReadFun(void)
{
    u32 toread;
    int rval;

    while(1)
    {
        mutex_lock(&dsplog_mutex);

        if(G_buf_fullness > 0)
        {
            toread = G_buf_fullness;

            if(toread > 0x10000)
            {
                toread = 0x10000;
            }

            break;
        }

        mutex_unlock(&dsplog_mutex);


        rval = wait_for_completion_timeout(&g_mdi_manager.dsp_compl.dsp_readlog_compl, 1 * HZ);

        if(rval <= 0)
        {
            if(rval == 0)
            {
                return 0;
            }

            return -EINTR;
        }



    }

    if(G_buffer_read_ptr + toread <= G_buffer_end)
    {
        sgks_mdi_log_WriteFile(G_buffer_read_ptr, toread);
        G_buffer_read_ptr += toread;
        G_buf_fullness -= toread;
    }
    else
    {
        u32 remain;
        u32 size1 = G_buffer_end - G_buffer_read_ptr;

        if(size1 > 0)
        {
            sgks_mdi_log_WriteFile(G_buffer_read_ptr, size1);
        }

        remain = toread - size1;

        if(remain > 0)
        {
            sgks_mdi_log_WriteFile(G_buffer, remain);
        }

        G_buffer_read_ptr = G_buffer + remain;
        G_buf_fullness -= toread;
    }

    mutex_unlock(&dsplog_mutex);
    return toread;

Error:
    mutex_unlock(&dsplog_mutex);
    return -EFAULT;

}



static int sgks_mdi_log_InitBuff(void)
{
    if((G_buffer = kmalloc(SGKS_DSP_LOG_SIZE, GFP_KERNEL)) == NULL)
    {
        return -ENOMEM;
    }

    G_buffer_read_ptr = G_buffer;
    G_buffer_write_ptr = G_buffer;
    G_buffer_end = G_buffer + SGKS_DSP_LOG_SIZE;
    return 0;
}

static void sgks_mdi_log_UpdateBuff()
{

    memcpy(G_buffer_write_ptr, dsp_log_blk, 32);
    G_buffer_write_ptr += 32;

    if(G_buffer_write_ptr >= G_buffer_end)
    {
        G_buffer_write_ptr = G_buffer;
    }

    if(G_buf_fullness < SGKS_DSP_LOG_SIZE)
    {
        G_buf_fullness += 32;
    }
    else
    {
        G_buffer_read_ptr = G_buffer_write_ptr;
    }


}


static int sgks_mdi_log_CapPthread2(void *arg)
{
    daemonize("sgks_debug2");
    while(1)
    {
        sgks_mdi_log_ReadFun();
        msleep(1);
    }

}

static int sgks_mdi_log_CapPthread(void *arg)
{
    daemonize("sgks_debug");
    struct file *filep;
    mm_segment_t fs;
    loff_t pos;
    int r_pos = 0;
    int flag = 0;
    memset(g_log_serv.log_mem_addr, 0, g_log_serv.log_mem_size);

    dsp_log_blk  = (sgks_icore_printf_s *)g_log_serv.log_mem_addr;
    u32 last_seq_num = 0;

    printk("log addr 0x%x, save file:%s, size:0x%x\n", g_log_serv.log_mem_addr, g_log_serv.log_file_path, g_log_serv.log_mem_size);

    while(1)
    {

        mutex_lock(&dsplog_mutex);

        while(1)
        {
            invalidate_d_cache(dsp_log_blk, 32);
            if(dsp_log_blk->seq_num < last_seq_num)
            {
                break;
            }

            last_seq_num = dsp_log_blk->seq_num;

            if(last_seq_num == 0)
            {
                break;
            }


            sgks_mdi_log_UpdateBuff();
            flag =1;

            dsp_log_blk++;
            r_pos+=32;


            if((u8 *)dsp_log_blk >= g_log_serv.log_mem_addr + g_log_serv.log_mem_size)
            {
                dsp_log_blk = (sgks_icore_printf_s *)g_log_serv.log_mem_addr;
            }
        }

        mutex_unlock(&dsplog_mutex);

        //if (flag ==1)
        {
            complete(&g_mdi_manager.dsp_compl.dsp_readlog_compl);
            flag = 0;
        }


    }

    printk("sgks_mdi_CapFwLogPthread exit..\n\n");

}

static int gks_mdi_ioc_log_CapStart(sgks_cap_dsp_log_file_s *data)
{

    sgks_cap_dsp_log_file_s *log_mem = data;

    memset(&g_log_serv, 0, sizeof(sgks_cap_dsp_log_file_s));
    memcpy(&g_log_serv,data, sizeof(sgks_cap_dsp_log_file_s));

    sgks_mdi_log_InitBuff();

    if(g_log_pthread == 0)
    {
        kernel_thread(sgks_mdi_log_CapPthread, NULL, 0);
        kernel_thread(sgks_mdi_log_CapPthread2, NULL, 0);
        g_log_pthread =1;
    }

    return 0;
}



void sgks_mdi_WriteMemFromFile(char *filename, u8 *buf, u32 size)
{

    struct file *filep;
    mm_segment_t fs;
    loff_t pos;
    int once = 0;

    printk("read file:%s to buf:0x%x, size:%x\n", filename, (u32)buf, size);

    filep = filp_open(filename, O_CREAT | O_RDWR, 0);

    if(IS_ERR(filep))
    {
        return -1;
    }

    fs = get_fs();
    set_fs(KERNEL_DS);
    pos = 0;
    vfs_read(filep, buf, size, &pos);
    filp_close(filep, 0);
    set_fs(fs);

}



void sgks_mdi_ioc_DumpMemToFile(char *filename, u64 addr, u32 size)
{

    struct file *filep;
    mm_segment_t fs;
    loff_t pos;
    int once = 0;
    u32 paddr = sgks6802_phys_to_virt(addr);

    printk("dump addr 0x%x, save file:%s, size:0x%x\n", paddr, filename, size);

    filep = filp_open(filename, O_CREAT | O_RDWR, 0);

    if(IS_ERR(filep))
    {
        return -1;
    }

    fs = get_fs();

    set_fs(KERNEL_DS);

    pos = 0;

    vfs_write(filep, paddr, size, &pos);

    filp_close(filep, 0);

    set_fs(fs);

}

//when dsp polls one cmd group from cmd queue, dsp will fetch all of the cmds
//and send a "sub dsp2 irq", which sets dsp_cmd_rx value to 1, to ACK on cmd receive
//in normal arm/dsp cmd protocol, there is no such ACK from DSP.
static inline int sgsk_mdi_irq_is_sub(void)
{

    sgks_dsp2_info_s *dsp2_info = NULL;

    dsp2_info = (sgks_dsp2_info_s *)g_mdi_manager.dsp_buff.dsp2_info.dsp2_info_ptr;
    invalidate_d_cache(dsp2_info, sizeof(*dsp2_info));

    if((dsp2_info->dsp_cmd_rx == 1) && (dsp2_info->dsp_msg_tx == 0))
    {
        //printk("turbo cmd received\n");
        return 1;
    }
    else
    {
        return 0;
    }
}


static int sgsk_mdi_irq_CheckDspCmdRecvSeq(u32 seq)
{

    sgks_dsp2_info_s *dsp2_info = NULL;
    u32 check_dsp_cmd_count = 0;

    dsp2_info = (sgks_dsp2_info_s *)g_mdi_manager.dsp_buff.dsp2_info.dsp2_info_ptr;
    

    while(1)
    {

		if (check_dsp_cmd_count >=100)
        {
            printk("Check Dsp Cmd Recv Seq err:[0x%x]\n",seq);
            return 0;
        }
	 
		invalidate_d_cache(dsp2_info, sizeof(*dsp2_info));

        if(dsp2_info->dsp_cmd_recv_seq == seq)
        {

            //printk("DspCmdRecv ok: 0x%x\n",seq);
            return 1;

        }

        printk("DspCmdRecv wait: [0x%x] [0x%x]\n",seq,dsp2_info->dsp_cmd_recv_seq);

        check_dsp_cmd_count++;

        mdelay(10);

    }

    return 0;

}


static void * sgks_mdi_dsp_change_mode()
{

    
    g_mdi_manager.dsp_buff.cmd_buff.normal_cmd_buffer.cmd_head.cmd_seq_num = 0;
	g_mdi_manager.dsp_buff.cmd_buff.normal_cmd_buffer.cmd_head.num_cmd = 0;
    g_mdi_manager.dsp_buff.result_queue.dsp_result_queue_ptr = g_mdi_manager.dsp_buff.result_queue.dsp_result_queue_start;

	u8 *ptr = (u8*)g_mdi_manager.dsp_buff.cmd_buff.normal_cmd_buffer.buffer_addr;

	memset(ptr, 0, g_mdi_manager.dsp_buff.cmd_buff.normal_cmd_buffer.buffer_size);

	clean_d_cache(ptr, g_mdi_manager.dsp_buff.cmd_buff.normal_cmd_buffer.buffer_size);

	printk("sgks_mdi_dsp_change_mode ok\n");

	return NULL;
	
}



void *sgks_mdi_irq_RevcMsg()
{

    if(sgsk_mdi_irq_is_sub())
    {
        return NULL;
    }

    void *irq_msg_pos = g_mdi_manager.dsp_buff.result_queue.dsp_result_queue_ptr;
    invalidate_d_cache(irq_msg_pos, SGKS_DSP_RESULT_SIZE);

    g_mdi_manager.dsp_buff.result_queue.dsp_result_queue_ptr += SGKS_DSP_RESULT_SIZE;

    if(g_mdi_manager.dsp_buff.result_queue.dsp_result_queue_ptr >= g_mdi_manager.dsp_buff.result_queue.dsp_result_queue_end)
    {
        g_mdi_manager.dsp_buff.result_queue.dsp_result_queue_ptr = g_mdi_manager.dsp_buff.result_queue.dsp_result_queue_start;
    }

    //encode_msg_t *msg = (encode_msg_t *)irq_msg_pos;
    //printk("msg->timecode %d, irq_msg_pos 0x%x\n",msg->timecode, irq_msg_pos);


    return irq_msg_pos;


}


static void sgks_mdi_isp_UpdateStatistics_ready()
{
    complete(&g_mdi_manager.dsp_compl.isp_statis_compl);

}



typedef struct aaa_tile_info_s
{
    u16 awb_tile_col_start;
    u16 awb_tile_row_start;
    u16 awb_tile_width;
    u16 awb_tile_height;
    u16 awb_tile_active_width;
    u16 awb_tile_active_height;
    u16 awb_rgb_shift;
    u16 awb_y_shift;
    u16 awb_min_max_shift;
    u16 ae_tile_col_start;
    u16 ae_tile_row_start;
    u16 ae_tile_width;
    u16 ae_tile_height;
    u16 ae_y_shift;
    u16 ae_linear_y_shift;
    u16 af_tile_col_start;
    u16 af_tile_row_start;
    u16 af_tile_width;
    u16 af_tile_height;
    u16 af_tile_active_width;
    u16 af_tile_active_height;
    u16 af_y_shift;
    u16 af_cfa_y_shift;
    u8  awb_tile_num_col;
    u8  awb_tile_num_row;
    u8  ae_tile_num_col;
    u8  ae_tile_num_row;
    u8  af_tile_num_col;
    u8  af_tile_num_row;
    u8  total_slices_x;
    u8  total_slices_y;
    u8  slice_index_x;
    u8  slice_index_y;
    u16 slice_width;
    u16 slice_height;
    u16 slice_start_x;
    u16 slice_start_y;

    u16 reserved[32];
} aaa_tile_info_t;


#define HIST_BIN_NUM    64

typedef struct rgb_histogram_stat_s
{
    u32 his_bin_y[HIST_BIN_NUM];
    u32 his_bin_r[HIST_BIN_NUM];
    u32 his_bin_g[HIST_BIN_NUM];
    u32 his_bin_b[HIST_BIN_NUM];
} rgb_histogram_stat_t;

typedef struct cfa_af_stat_s
{
    u16 sum_fy;
    u16 sum_fv1;
    u16 sum_fv2;
} cfa_af_stat_t;

typedef struct rgb_aaa_stat_s
{
    aaa_tile_info_t         tile_info;
    cfa_af_stat_t           af_stat[40];
    u16                     ae_sum_y[96];
    rgb_histogram_stat_t    histogram_stat;
    u8                      reserved[464];
} rgb_aaa_stat_t;

typedef struct cfa_awb_stat_s
{
    u16 sum_r;
    u16 sum_g;
    u16 sum_b;
    u16 count_min;
    u16 count_max;
} cfa_awb_stat_t;

typedef struct cfa_ae_stat_s
{
    u16 lin_y;
    u16 count_min;
    u16 count_max;
} cfa_ae_stat_t;

typedef struct cfa_histogram_stat_s
{
    u32 his_bin_r[HIST_BIN_NUM];
    u32 his_bin_g[HIST_BIN_NUM];
    u32 his_bin_b[HIST_BIN_NUM];
    u32 his_bin_y[HIST_BIN_NUM];
} cfa_histogram_stat_t;

typedef struct cfa_aaa_stat_s
{
    aaa_tile_info_t         tile_info;
    cfa_awb_stat_t          awb_stat[1024];
    cfa_ae_stat_t           ae_stat[96];
    cfa_af_stat_t           af_stat[40];
    cfa_histogram_stat_t    histogram_stat;
    u8                      reserved[208];
} cfa_aaa_stat_t;

static void sgks_mdi_irq_Get_yuv_Info(u32 dsp_op_mode, void *msg)
{
	if(dsp_op_mode == SGKS_DSP_ENCODE_MODE)
    {
        encode_msg_t *enc_msg = (encode_msg_t*)msg;
        /* ENC YUV */
        g_mdi_manager.user_yuv_info.encode_pts			= enc_msg->pts_val;
        g_mdi_manager.user_yuv_info.encode_seqnum		= 0;
        g_mdi_manager.user_yuv_info.encode_y_pic_addr	= enc_msg->encode_y_pic_addr - (u32)g_mdi_manager.dsp_buff.cap_info.cap_info_ptr;
        g_mdi_manager.user_yuv_info.encode_uv_pic_addr	= enc_msg->encode_uv_pic_addr - (u32)g_mdi_manager.dsp_buff.cap_info.cap_info_ptr;
        g_mdi_manager.user_yuv_info.encode_yuv_pitch	= enc_msg->encode_yuv_pitch;
        g_mdi_manager.user_yuv_info.encode_yuv_width    = enc_msg->encode_yuv_width;
        g_mdi_manager.user_yuv_info.encode_yuv_height	= enc_msg->encode_yuv_height;
        g_mdi_manager.user_yuv_info.rescale_y_pic_addr	= enc_msg->rescale_y_pic_addr - (u32)g_mdi_manager.dsp_buff.cap_info.cap_info_ptr;
        g_mdi_manager.user_yuv_info.rescale_uv_pic_addr	= enc_msg->rescale_uv_pic_addr - (u32)g_mdi_manager.dsp_buff.cap_info.cap_info_ptr;
        g_mdi_manager.user_yuv_info.rescale_yuv_pitch	= enc_msg->rescale_yuv_pitch;
        g_mdi_manager.user_yuv_info.rescale_yuv_height	= enc_msg->rescale_yuv_height;
        g_mdi_manager.user_yuv_info.rescale_yuv_width	= enc_msg->rescale_yuv_width;
        g_mdi_manager.user_yuv_info.rescale_yuv_type	= enc_msg->rescale_yuv_type;
    }
    else if(dsp_op_mode == SGKS_DSP_DECODE_MODE)
    {
		decode_msg_t *dec_msg = (decode_msg_t*)msg;

        /* VDEC YUV */
        g_mdi_manager.user_yuv_info.jpeg_y_addr 				  = dec_msg->jpeg_y_addr - (u32)g_mdi_manager.dsp_buff.cap_info.cap_info_ptr;
        g_mdi_manager.user_yuv_info.jpeg_uv_addr 				  = dec_msg->jpeg_uv_addr - (u32)g_mdi_manager.dsp_buff.cap_info.cap_info_ptr;
        g_mdi_manager.user_yuv_info.jpeg_width					  = dec_msg->jpeg_width;
        g_mdi_manager.user_yuv_info.jpeg_height					  = dec_msg->jpeg_height;
        g_mdi_manager.user_yuv_info.jpeg_pitch					  = dec_msg->jpeg_pitch;
		g_mdi_manager.user_yuv_info.jpeg_type					  = dec_msg->jpeg_type;
        g_mdi_manager.user_yuv_info.yuv422_y_addr				  = dec_msg->yuv422_y_addr - (u32)g_mdi_manager.dsp_buff.cap_info.cap_info_ptr;
        g_mdi_manager.user_yuv_info.yuv422_uv_addr				  = dec_msg->yuv422_uv_addr - (u32)g_mdi_manager.dsp_buff.cap_info.cap_info_ptr;
        g_mdi_manager.user_yuv_info.yuv422_width 				  = dec_msg->yuv422_width;
        g_mdi_manager.user_yuv_info.yuv422_height				  = dec_msg->yuv422_height;
        g_mdi_manager.user_yuv_info.yuv422_type					  = dec_msg->yuv422_type;
		g_mdi_manager.user_yuv_info.yuv422_pitch				  = dec_msg->yuv422_pitch;
        g_mdi_manager.user_yuv_info.second_rescale_buf_address_y  = dec_msg->second_rescale_buf_address_y - (u32)g_mdi_manager.dsp_buff.cap_info.cap_info_ptr;
        g_mdi_manager.user_yuv_info.second_rescale_buf_address_uv = dec_msg->second_rescale_buf_address_uv - (u32)g_mdi_manager.dsp_buff.cap_info.cap_info_ptr;
        g_mdi_manager.user_yuv_info.second_rescale_buf_pitch 	  = dec_msg->second_rescale_buf_pitch;
        g_mdi_manager.user_yuv_info.second_rescale_buf_width 	  = dec_msg->second_rescale_buf_width;
        g_mdi_manager.user_yuv_info.second_rescale_buf_height	  = dec_msg->second_rescale_buf_height;
        g_mdi_manager.user_yuv_info.second_rescale_buf_type		  = dec_msg->second_rescale_buf_type;
		
    }

}

static void sgks_mdi_irq_Save_dsp_EncStatus(encode_msg_t *msg)
{
    int i = 0;
    static u32 dwCurrentState = ENC_UNKNOWN_STATE;
    if(dwCurrentState != msg->encode_state)
    {
        DEBUGMSG(ZONE_INFO, ("State: op_mode=%d, sub_mode=%d, state=%d\n", msg->dsp_operation_mode, msg->encode_operation_mode, msg->encode_state));
        dwCurrentState =  msg->encode_state;
    }
    if((g_mdi_manager.dsp_status.stream_encode_state[0] != (msg->re_encode_state[0]&0xFF)) ||
            (g_mdi_manager.dsp_status.stream_encode_state[1] != (msg->re_encode_state[1]&0xFF)))
    {
        DEBUGMSG(ZONE_INFO, ("State: stream re_enc: %d, %d\n", (msg->re_encode_state[0]&0xFF), (msg->re_encode_state[1]&0xFF)));
		if ((msg->re_encode_state[0]&0xFF) ==1 && (msg->re_encode_state[1]&0xFF)==1 )
		{
			printk("enc switch ok!\n");
		}
    }
    g_mdi_manager.dsp_status.op_mode		= msg->dsp_operation_mode;
    g_mdi_manager.dsp_status.op_sub_mode	= msg->encode_operation_mode;
    g_mdi_manager.dsp_status.state		= msg->encode_state;
    
    for(i=0; i<4; i++)
    {
	     g_mdi_manager.dsp_status.stream_encode_state[i] = msg->re_encode_state[i]&0xFF;
    }
  
}


static void sgks_mdi_irq_Save_dsp_DecStatus(decode_msg_t *msg)
{

    g_mdi_manager.dsp_status.op_mode		= msg->dsp_operation_mode;
    g_mdi_manager.dsp_status.state		= msg->decode_state;

}

static int make_session_32bit_id(int stream, u8 index,  u32 *session_id)
{
    u32 session_id_tmp;

    if(index >= SESSION_ID_INDEX_SIZE)
    {
        DEBUGMSG(ZONE_ERROR, ("Fatal error, session index out of range\n"));
        return SGKS_FAIL;
    }
    session_id_tmp = g_stream_session_id[stream][index];
    if((session_id_tmp & 0xF) != index)
    {
        DEBUGMSG(ZONE_ERROR, ("Fatal error, expected session id record, index mismatch, session_id_tmp is 0x%x, index is %d \n",
                     session_id_tmp, index));
        return SGKS_FAIL;
    }

    *session_id = session_id_tmp;
    return SGKS_SUCCESS;
}

static int create_session_id(int stream)
{
    u32 random_data = 0;
    int index;
    
    get_random_bytes(&random_data, sizeof(u32));

    //update index before creation
    g_stream_session_index[stream]++;

    if(g_stream_session_index[stream] >= SESSION_ID_INDEX_SIZE)
    {
        g_stream_session_index[stream] = 0;
    }

    index = g_stream_session_index[stream];
    g_stream_session_id[stream][index] = (random_data & 0xFFFFFFF0);
    g_stream_session_id[stream][index] |= index;

    return SGKS_SUCCESS;
}

static inline void sgks_mdi_encode_prefetch_jpeg_sync(void)
{
    if((((g_enc_info.bits_desc_prefetch_ptr->stream_id)>>6)&0x3) == 1)
    { 
        if(atomic_read(&g_mdi_manager.dsp_compl.wait_yuv_to_enc_sync_done))
        {
            u32 jpeg_data_phy_addr = g_enc_info.bits_desc_prefetch_ptr->start_addr;
            u32 bsb_phy_start = (u32)g_mdi_manager.dsp_buff.bsb_info.bsb_phy_start;
            g_mdi_manager.jpeg_info.data_addr = g_mdi_manager.dsp_buff.bsb_info.bsb_user_start + (jpeg_data_phy_addr - bsb_phy_start);
            g_mdi_manager.jpeg_info.data_size = g_enc_info.bits_desc_prefetch_ptr->pic_size;           
            atomic_dec(&g_mdi_manager.dsp_compl.wait_yuv_to_enc_sync_done);
            complete(&g_mdi_manager.dsp_compl.yuv_to_enc_sync_cmpl);
        }
    }
}

static int sgks_mdi_put_one_encoded_frame(void)
{
    
    // refresh the prefetch read index
    invalidate_d_cache(g_enc_info.bits_desc_prefetch_ptr, sizeof(sgks_dsp_bits_info_s));

    if((g_enc_info.bits_desc_prefetch_ptr->PTS == ENC_INVALID_PTS) || (g_enc_info.bits_desc_prefetch_ptr->pic_size == 0))
    {
        DEBUGMSG(ZONE_ERROR, ("the frame is invalid\n"));
        return SGKS_SUCCESS;
    }
    sgks_dsp_bits_info_s *pBS_DESC = g_enc_info.bits_desc_prefetch_ptr;
    //DEBUGMSG(ZONE_THREAD, ("put:addr=0x%x, num=%d, type=%d, addr=0x%x\n", pBS_DESC, pBS_DESC->frame_num, pBS_DESC->pic_type, pBS_DESC->start_addr)); 
    sgks_mdi_encode_prefetch_jpeg_sync();

    up(&g_enc_info.sem_frame_counter);
    ++g_enc_info.total_pic_counter;

    if(++g_enc_info.bits_desc_prefetch_ptr >= g_enc_info.bits_desc_end)
    {
        g_enc_info.bits_desc_prefetch_ptr = g_enc_info.bits_desc_start;
    }
/*   
    u32 framenum;
    if((u32)g_enc_info.bits_desc_prefetch_ptr > (u32)g_enc_info.bits_desc_read_ptr)
    {
        framenum = ((u32)g_enc_info.bits_desc_prefetch_ptr - (u32)g_enc_info.bits_desc_read_ptr) / sizeof(sgks_dsp_bits_info_s);
    }
    else
    {
        framenum = NUM_BS_DESC - ((u32)g_enc_info.bits_desc_read_ptr - (u32)g_enc_info.bits_desc_prefetch_ptr) / sizeof(sgks_dsp_bits_info_s);
    }
    DEBUGMSG(ZONE_VENC, ("%d frame not read\n", framenum));
*/    
    return SGKS_SUCCESS;
}

static int sgks_mdi_put_encoded_frame(encode_msg_t *pEncMsg)
{
    u32 frame_count;
    u32 info_addr;
    u32 bs_desc_vir_addr;
    sgks_dsp_bits_info_s *pBS_Desc = NULL;
    u32 jj = 0;
    int offset = 0;
    u32 bs_desc_start_phy = (u32)g_mdi_manager.dsp_buff.bsb_info.bs_desc_phy_start;
    u32 bs_desc_start_kernel = (u32)g_mdi_manager.dsp_buff.bsb_info.bs_desc_kernel_start;
    
    
    frame_count = pEncMsg->total_pic_encoded_h264_mode + pEncMsg->total_pic_encoded_mjpeg_mode - pre_pic_total;
    pre_pic_total = pEncMsg->total_pic_encoded_h264_mode + pEncMsg->total_pic_encoded_mjpeg_mode;
    info_addr = pEncMsg->h264_info_fifo_next - frame_count*sizeof(sgks_dsp_bits_info_s);
    if(info_addr<bs_desc_start_phy)
    {
        info_addr = (pEncMsg->h264_info_fifo_size + bs_desc_start_phy) - 0x20*(frame_count - (pEncMsg->h264_info_fifo_next - bs_desc_start_phy)/0x20);
        //DEBUGMSG(ZONE_VENC, ("put: tail frame\n"));
    }
    //DEBUGMSG(ZONE_VENC, ("put: count=%d, info_addr=0x%x\n", frame_count, info_addr));
    bs_desc_vir_addr =  bs_desc_start_kernel + (info_addr - bs_desc_start_phy);
    pBS_Desc = (sgks_dsp_bits_info_s *)bs_desc_vir_addr;
    for(jj=0; jj<frame_count; jj++)
    {
        offset = (u32)pBS_Desc - (bs_desc_start_kernel + g_mdi_manager.dsp_buff.bsb_info.bs_desc_size);
        if(offset >= 0)
        {
            pBS_Desc = (sgks_dsp_bits_info_s *)(bs_desc_start_kernel + offset*0x20);
        }
        g_enc_info.bits_desc_prefetch_ptr = pBS_Desc;
        invalidate_d_cache(g_enc_info.bits_desc_prefetch_ptr, sizeof(sgks_dsp_bits_info_s));
        if((g_enc_info.bits_desc_prefetch_ptr->PTS == ENC_INVALID_PTS) || (g_enc_info.bits_desc_prefetch_ptr->pic_size == 0))
        {
            DEBUGMSG(ZONE_ERROR, ("this frame is invalid\n"));
            DEBUGMSG(ZONE_VENC, ("put: info_next=0x%x, info_phy=0x%x, info_ker=0x%x\n", pEncMsg->h264_info_fifo_next,  info_addr, pBS_Desc));	
            return SGKS_SUCCESS;
        }
        sgks_mdi_encode_prefetch_jpeg_sync();
        up(&g_enc_info.sem_frame_counter);

        //DEBUGMSG(ZONE_VENC, ("put:0x%x, %d, %d\n", pBS_Desc, ((pBS_Desc->stream_id)>>6)&0x3, pBS_Desc->frame_num));
        pBS_Desc +=1;
    }
    return SGKS_SUCCESS;
}

static int sgks_mdi_encode_read_fifo(sgks_mdi_enc_bits_info *pBitsInfo)
{
    sgks_mdi_enc_bits_info bits_info, *pd;
    sgks_dsp_bits_info_s *read_index = NULL;
    int stream_id = 0;
    
    if(down_timeout(&g_enc_info.sem_frame_counter, msecs_to_jiffies(1000)) != 0)
    {
        DEBUGMSG(ZONE_ERROR, ("%s timeout\n", __FUNCTION__));
        return SGKS_FAIL;
    }

    if(g_enc_info.bits_desc_read_ptr == g_enc_info.bits_desc_prefetch_ptr)
    {
        DEBUGMSG(ZONE_ERROR, ("read:no data\n"));
        DEBUGMSG(ZONE_VENC, ("read:0x%x\n", g_enc_info.bits_desc_read_ptr));	
        return SGKS_FAIL;
    }
    read_index = g_enc_info.bits_desc_read_ptr;
    invalidate_d_cache((void *)(read_index), sizeof(sgks_dsp_bits_info_s));
    
    //DEBUGMSG(ZONE_VENC, ("get:0x%x, %d, %d\n", read_index, ((read_index->stream_id)>>6)&0x3, read_index->frame_num));

    if((read_index->PTS == ENC_INVALID_PTS) || (read_index->pic_size == 0))
    {
       DEBUGMSG(ZONE_ERROR, ("%s PTS Invalid or pic_size is 0\n", __FUNCTION__));
       return SGKS_FAIL;
    }
    stream_id = ((read_index->stream_id)>>6)&0x3;
    if(stream_id >= MAX_ENCODE_STREAMS_NUM)
    {
        DEBUGMSG(ZONE_ERROR, ("%s frame stream id error %d \n", __FUNCTION__, stream_id));
        return SGKS_FAIL;
    }
    
    sgks_dsp_bits_info_s *previous_index = NULL;
    //advance to next descriptor, so clear previous descriptor
    if(read_index > g_enc_info.bits_desc_start)
    { 
        previous_index = read_index - 1;
    }
    else
    { 
        previous_index = g_enc_info.bits_desc_end - 1; // bits_desc_end is exclusive
    }    
    //update PTS of previous descriptor to invalid
    previous_index->PTS = ENC_INVALID_PTS;
    previous_index->pic_size = 0;
    previous_index->stream_id = 0; 
    clean_d_cache((void *)(previous_index), sizeof(*previous_index));    

    pd = &bits_info;
    memset(pd, 0, sizeof(sgks_mdi_enc_bits_info));
    pd->frame_num = read_index->frame_num;
    pd->PTS = read_index->PTS;
    pd->start_addr = read_index->start_addr;
    if(read_index->pic_type == DSP_PIC_TYPE_MJPEG_FRAME)
    { 
        pd->pic_type = ENC_JPEG_STREAM;
    }
    else
    { 
        pd->pic_type = read_index->pic_type;
    }

    pd->level_idc = read_index->level_idc;
    pd->ref_idc = read_index->ref_idc;
    pd->pic_struct = read_index->pic_struct;
    pd->pic_size = read_index->pic_size;
    pd->channel_id = 0;
    pd->stream_id = stream_id;
    pd->cavlc_pjpeg = 0;
    
    u32 session_id;
    u8 session_index = read_index->session_id & 0xF;
    if(make_session_32bit_id(pd->stream_id, session_index, &session_id) < 0)
    {
        DEBUGMSG(ZONE_ERROR, ("unexpected 32 session id generation error \n"));
        return SGKS_FAIL;
    }
    else
    {
        pd->session_id = session_id;
    }
    //DEBUGMSG(ZONE_THREAD, ("get:num=%d, type=%d, addr=0x%x, size=0x%x\n", pd->frame_num, pd->pic_type, pd->start_addr, pd->pic_size));     
  
    if ((pd->start_addr == 0xFFFFFFFF) || (pd->pic_size == 0xFFFFFF) || (pd->PTS == 0xFFFFFFFF))  
    {
        DEBUGMSG(ZONE_THREAD, ("Sent STREAM END null frame for stream %c.\n", 'A' + pd->stream_id));
        pd ->stream_end = 1;    //mark as end of frame sign
        goto next_read_entry;
    }
   
   // picture real size
    u32 align_size = pd->pic_size & (~(1 << 23));
    if(align_size == 0xffffff)
    {
        DEBUGMSG(ZONE_THREAD, ("spurious frame\n"));
    }
   
    else
    {
        // address translation and cache sync.
        u32 offset, align_addr;
        u8 *bsb_user_start_addr = NULL;
        u8 *bsb_user_end_addr = NULL;

        bsb_user_start_addr = g_mdi_manager.dsp_buff.bsb_info.bsb_user_start;
        bsb_user_end_addr = bsb_user_start_addr + g_mdi_manager.dsp_buff.bsb_info.bsb_size;
        
        offset = pd->start_addr - (u32)(g_mdi_manager.dsp_buff.bsb_info.bsb_phy_start);     
        pd->start_addr = offset + (u32)(g_mdi_manager.dsp_buff.bsb_info.bsb_user_start);
       
        align_addr = (pd->start_addr & ~31);
        if(((u8 *)pd->start_addr < bsb_user_start_addr) || ((u8 *)pd->start_addr >= bsb_user_end_addr))
        {
            DEBUGMSG(ZONE_ERROR, ("%s: start_addr:%x error\n", __FUNCTION__, pd->start_addr));
            return SGKS_FAIL;
        }

        mutex_lock(&g_enc_info.bsb_mem_mutex);
        if(((u8 *)align_addr + align_size) > bsb_user_end_addr)
        {
            invalidate_d_cache((void *)align_addr, (u32)(bsb_user_end_addr - align_addr));
            invalidate_d_cache((void *)bsb_user_start_addr, (u32)(align_addr + align_size - (u32)bsb_user_end_addr));
        }
        else
        {
            invalidate_d_cache((void *)align_addr, align_size);
        }
        mutex_unlock(&g_enc_info.bsb_mem_mutex);
    }
   
next_read_entry:
      
    // update bits desc read index
    if(++g_enc_info.bits_desc_read_ptr == g_enc_info.bits_desc_end)
    {
        g_enc_info.bits_desc_read_ptr = g_enc_info.bits_desc_start;
    }
    memcpy(pBitsInfo, &bits_info, sizeof(sgks_dsp_bits_info_s));
    return SGKS_SUCCESS;
    
}

static void sgks_mdi_irq_parse_encode_msg(encode_msg_t *msg)
{

    sgks_mdi_mmap_s addrmmap;
    int *data_arrived = NULL;
    static int prev_encode_status = ENC_IDLE_STATE;
    rgb_aaa_stat_t *pRgb = NULL;
    cfa_aaa_stat_t *pCfa  = NULL;
    u32 h264_pic_count, mjpeg_pic_count, jpeg_pic_count;
    //static int flag = 0;
    
    if(msg->total_pic_encoded_h264_mode == 0)
    {
        g_enc_info.total_pic_encoded_h264_mode = 0;
        g_enc_info.h264_pic_counter = 0;
    }

    if(msg->total_pic_encoded_mjpeg_mode == 0)
    {
        g_enc_info.total_pic_encoded_mjpeg_mode = 0;
        g_enc_info.mjpeg_pic_counter = 0;
        g_enc_info.current_encode_state = ENC_IDLE_STATE;
    }

    if((msg->total_pic_encoded_h264_mode == 0) && (msg->total_pic_encoded_mjpeg_mode == 0))
    {
        g_enc_info.total_pic_counter = 0;
    }

    if(msg->total_pic_encoded_jpeg_mode == 0)
    {
        g_enc_info.total_pic_encoded_jpeg_mode = 0;
        g_enc_info.jpeg_pic_counter = 0;
        g_enc_info.current_encode_state = ENC_IDLE_STATE;
    }
    switch(msg->encode_operation_mode)
    {
        case DSP_ENC_PRE_MODE:
        {
            u32 cur_enc_state = msg->encode_state;
            if(cur_enc_state == ENC_BUSY_STATE)
            {
                h264_pic_count = msg->total_pic_encoded_h264_mode - g_enc_info.total_pic_encoded_h264_mode;
                mjpeg_pic_count = msg->total_pic_encoded_mjpeg_mode - g_enc_info.total_pic_encoded_mjpeg_mode;
                g_enc_info.total_pic_encoded_h264_mode = msg->total_pic_encoded_h264_mode;
                g_enc_info.total_pic_encoded_mjpeg_mode = msg->total_pic_encoded_mjpeg_mode;
                g_enc_info.h264_pic_counter += h264_pic_count;
                g_enc_info.mjpeg_pic_counter += mjpeg_pic_count;
            }

            if((cur_enc_state == ENC_IDLE_STATE) && (prev_encode_status == ENC_BUSY_STATE))
            {
                g_enc_info.total_pic_encoded_h264_mode = 0;
                g_enc_info.h264_pic_counter = 0;
                g_enc_info.total_pic_counter = 0;
                g_enc_info.sem_frame_counter.count = 0;
                g_enc_info.mjpeg_pic_counter = 0;
                pre_pic_total = 0;
                
                g_enc_info.bits_desc_prefetch_ptr = (sgks_dsp_bits_info_s *)g_mdi_manager.dsp_buff.bsb_info.bs_desc_kernel_start;
                g_enc_info.bits_desc_read_ptr = (sgks_dsp_bits_info_s *)g_mdi_manager.dsp_buff.bsb_info.bs_desc_kernel_start;
                DEBUGMSG(ZONE_INFO, ("dsp state change: busy -> idle\n"));
            }
            
            prev_encode_status = cur_enc_state;
#if 0
            {
                int i, delta;
                delta = (g_enc_info.h264_pic_counter + g_enc_info.mjpeg_pic_counter) - g_enc_info.total_pic_counter;
                if(unlikely(delta > 0))
                {
                    for(i = 0; i < delta; ++i)
                    {
                        sgks_mdi_put_one_encoded_frame();
                    }
                }
            }
#else
            {
                int delta;
                delta = (g_enc_info.h264_pic_counter + g_enc_info.mjpeg_pic_counter) - g_enc_info.total_pic_counter;
                if(unlikely(delta > 0))
                {
                   sgks_mdi_put_encoded_frame(msg);
                }
            }
#endif
            if(g_mdi_manager.dsp_compl.yuv_to_enc_compl_wait_count)
            {
                g_mdi_manager.dsp_compl.yuv_to_enc_compl_wait_count--;
                complete(&g_mdi_manager.dsp_compl.yuv_to_enc_compl);
            }
            break;
        }
        case DSP_MJPEG_PRE_MODE:
        {
            if(msg->encode_state == ENC_BUSY_STATE)
            {
                jpeg_pic_count = msg->total_pic_encoded_jpeg_mode -g_enc_info.total_pic_encoded_jpeg_mode;
                g_enc_info.total_pic_encoded_jpeg_mode = msg->total_pic_encoded_jpeg_mode;
                g_enc_info.jpeg_pic_counter += jpeg_pic_count;
            }
            break;
        }

        case DSP_SJPEG_PRE_MODE:
        case DSP_ROW_DATA_MODE:
        default:
        break;
    }
}

static void sgks_mdi_irq_isp_update(encode_msg_t *msg)
{

    if((msg->aaa_data_fifo_next == NULL) && (msg->yuv_aaa_data_fifo_next == NULL) && (msg->raw_pic_addr == NULL))
    {
        //printk("irq_isp_update NULL\n");
    }
	
#if 0	
	 printk("=sgks_mdi_irq_isp_update=======aaa_data_fifo_next 0x%x, ======== yuv_aaa_data_fifo_next 0x%x, ====== raw_pic_addr 0x%x\n"
               ,msg->aaa_data_fifo_next
               ,msg->yuv_aaa_data_fifo_next
               ,msg->raw_pic_addr);
#endif

    if((msg->aaa_data_fifo_next != NULL) || (msg->yuv_aaa_data_fifo_next != NULL) || (msg->raw_pic_addr != NULL))
    {

        if (msg->yuv_aaa_data_fifo_next != NULL)
        {
            g_mdi_manager.isp_statistics.isp_rgb_aaa_ptr      			= g_mdi_manager.isp_statistics.isp_rgb_aaa_ptr_next;
            g_mdi_manager.isp_statistics.isp_rgb_aaa_ptr_next 			= sgks6802_phys_to_virt(msg->yuv_aaa_data_fifo_next);
            g_mdi_manager.isp_user_statistics_pos.isp_rgb_aaa_ptr_pos 	= g_mdi_manager.isp_statistics.isp_rgb_aaa_ptr - g_mdi_manager.isp_buff.isp_aaa_fifo1_base;

            invalidate_d_cache(g_mdi_manager.isp_statistics.isp_rgb_aaa_ptr, MDI_RGB_AAA_DATA_BLOCK);

#if 0
            printk("=<%d>==copy rgb info=======cur read 0x%x, ======== cur read pos %d, ====== next read 0x%x\n"
                   ,msg->timecode
                   ,g_mdi_manager.isp_statistics.isp_rgb_aaa_ptr
                   , g_mdi_manager.isp_user_statistics_pos.isp_rgb_aaa_ptr_pos
                   ,msg->yuv_aaa_data_fifo_next);

            pRgb = (rgb_aaa_stat_t *)g_mdi_manager.isp_statistics.isp_rgb_aaa_ptr;

            printk("dd RGB Hist bin [32] %d %d %d %d.\n"
                   ,pRgb->histogram_stat.his_bin_y[32]
                   ,pRgb->histogram_stat.his_bin_r[32]
                   ,pRgb->histogram_stat.his_bin_g[32]
                   ,pRgb->histogram_stat.his_bin_b[32]);

            printk("dd pRgb->ae_sum_y  %d %d %d %d.\n"
                   ,pRgb->ae_sum_y[0]
                   ,pRgb->ae_sum_y[1]
                   ,pRgb->ae_sum_y[2]
                   ,pRgb->ae_sum_y[3]);
#endif

        }

        if (msg->aaa_data_fifo_next != NULL)
        {

            g_mdi_manager.isp_statistics.isp_cfa_aaa_ptr	     			= g_mdi_manager.isp_statistics.isp_cfa_aaa_ptr_next;
            g_mdi_manager.isp_statistics.isp_cfa_aaa_ptr_next 			= sgks6802_phys_to_virt(msg->aaa_data_fifo_next);
            g_mdi_manager.isp_user_statistics_pos.isp_cfa_aaa_ptr_pos 	= g_mdi_manager.isp_statistics.isp_cfa_aaa_ptr - g_mdi_manager.isp_buff.isp_aaa_fifo2_base;

            invalidate_d_cache(g_mdi_manager.isp_statistics.isp_cfa_aaa_ptr, MDI_CFA_AAA_DATA_BLOCK);
#if 0
            printk("=<%d>==copy cfa info=======cur read 0x%x, ======== cur read pos %d, ====== next read 0x%x\n"
                   ,msg->timecode
                   ,g_mdi_manager.isp_statistics.isp_cfa_aaa_ptr
                   , g_mdi_manager.isp_user_statistics_pos.isp_cfa_aaa_ptr_pos
                   ,msg->aaa_data_fifo_next);

            pCfa = (struct cfa_aaa_stat_s *)g_mdi_manager.isp_statistics.isp_cfa_aaa_ptr;

            pCfa->tile_info.total_slices_x = 1;
            printk("AWB %d %d %d %d %d\n", pCfa->tile_info.awb_tile_num_col, pCfa->tile_info.awb_tile_num_row, pCfa->tile_info.awb_tile_width, pCfa->tile_info.awb_tile_height, pCfa->tile_info.awb_rgb_shift);
            printk("AE %d %d %d %d %d\n", pCfa->tile_info.ae_tile_num_col, pCfa->tile_info.ae_tile_num_row, pCfa->tile_info.ae_tile_width, pCfa->tile_info.ae_tile_height, pCfa->tile_info.ae_linear_y_shift);
            printk("%dslice %d %d %d %d\n", pCfa->tile_info.slice_index_x, pCfa->tile_info.ae_tile_num_col, pCfa->tile_info.ae_tile_num_row, pCfa->tile_info.awb_tile_num_row, pCfa->tile_info.awb_tile_num_col);
            printk("awb %d %d %d %d %d\n", pCfa->awb_stat[511].sum_r, pCfa->awb_stat[511].sum_g, pCfa->awb_stat[511].sum_b, pCfa->awb_stat[511].count_min, pCfa->awb_stat[511].count_max);

            printk("CFA Hist bin [32] %d %d %d %d.\n", pCfa->histogram_stat.his_bin_y[32], pCfa->histogram_stat.his_bin_r[32],
                   pCfa->histogram_stat.his_bin_g[32], pCfa->histogram_stat.his_bin_b[32]);
#endif

        }

        if (msg->raw_pic_addr != NULL)
        {
        	#if 0
            g_mdi_manager.isp_statistics.isp_hist_aaa_ptr =  sgks6802_phys_to_virt(msg->raw_pic_addr);
            g_mdi_manager.isp_statistics.isp_hist_pitch   = msg->raw_pic_pitch;

            if (g_mdi_manager.isp_user_statistics.isp_hist_aaa_ptr != NULL)
            {
                data_arrived = (int *)g_mdi_manager.isp_user_statistics.isp_hist_aaa_ptr;
                *data_arrived = 1;
                memcpy(g_mdi_manager.isp_user_statistics.isp_hist_aaa_ptr + sizeof(int), g_mdi_manager.isp_statistics.isp_hist_aaa_ptr, 0x10000);
            }
            invalidate_d_cache(g_mdi_manager.isp_statistics.isp_hist_aaa_ptr, g_mdi_manager.isp_statistics.isp_hist_pitch  * 1540  + sizeof(int));
			#endif
        }

        sgks_mdi_isp_UpdateStatistics_ready();

    }

}


__inline static void sgks_mdi_CRYPTO_set_DES_Key(uint8_t index, u32 data)
{
	sgks_writel((REG_CRYPTO_DES_KEY + index * 0x00000004), data);
}


__inline static u32  sgks_mdi_CRYPTO_set_DES_KeySource(u32 data)
{
	sgks_writel(REG_CRYPTO_EFUSE_BOOT_SW_DIS, data);
}



__inline static void sgks_mdi_CRYPTO_set_AES_128_Key(uint8_t index, u32 data)
{
	sgks_writel((REG_CRYPTO_AES_128_KEY - index * 0x00000004), data);
}

__inline static void sgks_mdi_CRYPTO_set_AES_192_Key(uint8_t index, u32 data)
{
	sgks_writel((REG_CRYPTO_AES_192_KEY - index * 0x00000004), data);
}

__inline static void sgks_mdi_CRYPTO_set_AES_256_Key(uint8_t index, u32 data)
{
	sgks_writel((REG_CRYPTO_AES_256_KEY - index * 0x00000004), data);
}

__inline static void sgks_mdi_CRYPTO_set_DES_Interrupt_En(uint8_t data)
{
	sgks_crypto_des_interrupt_s d;
	d.all = sgks_readl(REG_CRYPTO_DES_INTERRUPT);
	d.bitc.en = data;
	sgks_writel(REG_CRYPTO_DES_INTERRUPT, d.all);
}

__inline static void sgks_mdi_CRYPTO_set_DES_Opcode(u32 data)
{
	sgks_writel(REG_CRYPTO_DES_OPCODE, data);
}


__inline static u32  sgks_mdi_CRYPTO_set_DES_DataSourceMode(u32 data)
{
	sgks_writel(REG_CRYPTO_SHIFT_BYTE, data);
}


__inline static void sgks_mdi_CRYPTO_set_DES_Input(uint8_t index, u32 data)
{
	sgks_writel(REG_CRYPTO_DES_INPUT, data);
}




__inline sgks_mdi_CRYPTO_set_START_LENGTH(u32 data)
{
	sgks_writel(REG_CRYPTO_START_LENGTH, data);
}



__inline static u32  sgks_mdi_CRYPTO_get_DES_Output(uint8_t index)
{
	u32 value = sgks_readl(REG_CRYPTO_DES_OUTPUT);
	return value;
}

__inline static u32  sgks_mdi_CRYPTO_get_DES_Output_Rdy(void)
{
	u32 value = sgks_readl(REG_CRYPTO_DES_OUTPUT_RDY);
	return value;
}

__inline static void sgks_mdi_CRYPTO_set_AES_Opcode(u32 data)
{
	sgks_writel(REG_CRYPTO_AES_OPCODE, data);
}

__inline static void sgks_mdi_CRYPTO_set_AES_Input(uint8_t index, u32 data)
{
	sgks_writel((REG_CRYPTO_AES_INPUT - index * 0x00000004), data);
}

__inline static u32  sgks_mdi_CRYPTO_get_AES_Output(uint8_t index)
{
	u32 value = sgks_readl(REG_CRYPTO_AES_OUTPUT - index * 0x00000004);
	return value;
}

__inline static u32  sgks_mdi_CRYPTO_get_AES_Output_Rdy(void)
{
	u32 value = sgks_readl(REG_CRYPTO_AES_OUTPUT_RDY);
	return value;
}





static int sgks_mdi_crypto_ProcessData(sgks_crypto_case_s *crypto, u32 type)
{
	int i, nkey;
	sgks_crypto_mode_e mode;
	sgks_crypto_data_s *data_in;
	sgks_crypto_data_s *data_out;
	static int init_flag = 1;

	if(init_flag == 1)
	{
		nkey = 2;

		for(i = 0; i < nkey; i++)
		{
			sgks_mdi_CRYPTO_set_DES_Key(i, crypto->pkey.key[i]);
		}

		sgks_mdi_CRYPTO_set_DES_KeySource(0);
		sgks_mdi_CRYPTO_set_DES_KeySource(2);
		sgks_mdi_CRYPTO_set_DES_Opcode(1);
		sgks_mdi_CRYPTO_set_DES_DataSourceMode(8);
		init_flag = 0;
	}

	mode = crypto->mode;

	switch(mode)
	{
		case SGKS_CRYPTO_DES:
			data_in = &(crypto->source);

			if(type == SGKS_CRYPTO_ENCRPT)
			{
				data_out = &(crypto->enc_dest);
			}
			else
			{
				data_out = &(crypto->dec_dest);
			}

			sgks_mdi_CRYPTO_set_START_LENGTH(33 | 0x1);
			sgks_mdi_CRYPTO_set_DES_Input(0, data_in->des_data.data_hi);
			sgks_mdi_CRYPTO_set_DES_Input(1, data_in->des_data.data_lo);

			while(!sgks_mdi_CRYPTO_get_DES_Output_Rdy())
			{
				;
			}

			data_out->des_data.data_hi = sgks_mdi_CRYPTO_get_DES_Output(0);
			data_out->des_data.data_lo = sgks_mdi_CRYPTO_get_DES_Output(1);
			break;
		case SGKS_CRYPTO_AES_128:
			nkey = 4;

			for(i = 0; i < nkey; i++)
			{
				sgks_mdi_CRYPTO_set_AES_128_Key(i, crypto->pkey.key[i]);
			}

			data_in = &(crypto->source);

			if(type == SGKS_CRYPTO_ENCRPT)
			{
				data_out = &(crypto->enc_dest);
			}
			else
			{
				data_out = &(crypto->dec_dest);
			}

			sgks_mdi_CRYPTO_set_AES_Opcode(type);
			sgks_mdi_CRYPTO_set_AES_Input(0, data_in->aes_data.data_127_96);
			sgks_mdi_CRYPTO_set_AES_Input(1, data_in->aes_data.data_95_64);
			sgks_mdi_CRYPTO_set_AES_Input(2, data_in->aes_data.data_63_32);
			sgks_mdi_CRYPTO_set_AES_Input(3, data_in->aes_data.data_31_0);

			while(!sgks_mdi_CRYPTO_get_AES_Output_Rdy())
			{
				;
			}

			data_out->aes_data.data_127_96 = sgks_mdi_CRYPTO_get_AES_Output(0);
			data_out->aes_data.data_95_64  = sgks_mdi_CRYPTO_get_AES_Output(1);
			data_out->aes_data.data_63_32  = sgks_mdi_CRYPTO_get_AES_Output(2);
			data_out->aes_data.data_31_0   = sgks_mdi_CRYPTO_get_AES_Output(3);
			break;
		case SGKS_CRYPTO_AES_192:
			nkey = 6;

			for(i = 0; i < nkey; i++)
			{
				sgks_mdi_CRYPTO_set_AES_192_Key(i, crypto->pkey.key[i]);
			}

			data_in = &(crypto->source);

			if(type == SGKS_CRYPTO_ENCRPT)
			{
				data_out = &(crypto->enc_dest);
			}
			else
			{
				data_out = &(crypto->dec_dest);
			}

			sgks_mdi_CRYPTO_set_AES_Opcode(type);
			sgks_mdi_CRYPTO_set_AES_Input(0, data_in->aes_data.data_127_96);
			sgks_mdi_CRYPTO_set_AES_Input(1, data_in->aes_data.data_95_64);
			sgks_mdi_CRYPTO_set_AES_Input(2, data_in->aes_data.data_63_32);
			sgks_mdi_CRYPTO_set_AES_Input(3, data_in->aes_data.data_31_0);

			while(!sgks_mdi_CRYPTO_get_AES_Output_Rdy())
			{
				;
			}

			data_out->aes_data.data_127_96 = sgks_mdi_CRYPTO_get_AES_Output(0);
			data_out->aes_data.data_95_64  = sgks_mdi_CRYPTO_get_AES_Output(1);
			data_out->aes_data.data_63_32  = sgks_mdi_CRYPTO_get_AES_Output(2);
			data_out->aes_data.data_31_0   = sgks_mdi_CRYPTO_get_AES_Output(3);
			break;
		case SGKS_CRYPTO_AES_256:
			nkey = 8;

			for(i = 0; i < nkey; i++)
			{
				sgks_mdi_CRYPTO_set_AES_256_Key(i, crypto->pkey.key[i]);
			}

			data_in = &(crypto->source);

			if(type == SGKS_CRYPTO_ENCRPT)
			{
				data_out = &(crypto->enc_dest);
			}
			else
			{
				data_out = &(crypto->dec_dest);
			}

			sgks_mdi_CRYPTO_set_AES_Opcode(type);
			sgks_mdi_CRYPTO_set_AES_Input(0, data_in->aes_data.data_127_96);
			sgks_mdi_CRYPTO_set_AES_Input(1, data_in->aes_data.data_95_64);
			sgks_mdi_CRYPTO_set_AES_Input(2, data_in->aes_data.data_63_32);
			sgks_mdi_CRYPTO_set_AES_Input(3, data_in->aes_data.data_31_0);

			while(!sgks_mdi_CRYPTO_get_AES_Output_Rdy())
			{
				;
			}

			data_out->aes_data.data_127_96 = sgks_mdi_CRYPTO_get_AES_Output(0);
			data_out->aes_data.data_95_64  = sgks_mdi_CRYPTO_get_AES_Output(1);
			data_out->aes_data.data_63_32  = sgks_mdi_CRYPTO_get_AES_Output(2);
			data_out->aes_data.data_31_0   = sgks_mdi_CRYPTO_get_AES_Output(3);
			break;
		case SGKS_CRYPTO_MODE_MAX:
		default:
			break;
	}

	return 0;
}


static void sgks_mdi_irq_parse_vdec_msg(decode_msg_t *msg)
{

    if( msg->decode_state == SGKS_DEC_H264DEC_STATE)
    {
        g_mdi_manager.vdec_info.curr_pts			= 0;
        g_mdi_manager.vdec_info.curr_pts_high		= 0;

        g_mdi_manager.vdec_info.decoded_frames	= msg->decoded_pic_number;
        g_mdi_manager.vdec_buff_pos.curr_pos  	= msg->h264_bits_fifo_next - g_mdi_manager.vdec_buff.buff_phy;

#if 0
        printk("2 msg->h264_bits_fifo_next 0x%x pos %d deccount %d\n"
               ,msg->h264_bits_fifo_next
               ,g_mdi_manager.vdec_buff_pos.curr_pos
               ,g_mdi_manager.vdec_info.decoded_frames);
#endif

    }

//printk("decode_compl_wait_count %d\n",g_mdi_manager.dsp_compl.decode_compl_wait_count);

    //  if (g_mdi_manager.dsp_compl.decode_compl_wait_count > 0)
    {
        //    g_mdi_manager.dsp_compl.decode_compl_wait_count--;
        complete(&g_mdi_manager.dsp_compl.decode_compl);
    }


}



static void sgks_mdi_CheckDspCmd(u8* dsp_normal_buff, u32 dsp_normal_num, u32 curr_cmd_seq)
{

    u8 *dsp_cmd_ptr  = NULL;
    u32 dsp_cmd_code = 0x0;
    int i = 0;

    dsp_cmd_ptr = dsp_normal_buff + sizeof(sgks_dsp_cmd_header_s);

    //printk("[send dsp normalB 2] dsp_normal_buff num_cmd %d\n",dsp_normal_num);

    for (i=0; i<dsp_normal_num; i++)
    {
        dsp_cmd_code = *(u32*)dsp_cmd_ptr;

        //printk("[send dsp normalB 3] [%d] [0x%x]\n", i, dsp_cmd_code);

        //reset op mode
        if (dsp_cmd_code == 0x1006)
        {
            if (sgsk_mdi_irq_CheckDspCmdRecvSeq(curr_cmd_seq) == 1)
            {
                sgks_mdi_dsp_change_mode(dsp_normal_buff);
                break;
            }

        }

        dsp_cmd_ptr += SGKS_DSP_CMD_SIZE;

    }

}


void sgks_mdi_cmd_transfer(u32 dsp_op_mode)
{

    sgks_dsp_cmd_header_s *mdi_cmdq_header    = NULL;
    sgks_dsp_cmd_header_s *dsp_cmdq_header    = NULL;
    u8 *mdi_normal_buff						= NULL;
    u8 *dsp_normal_buff						= NULL;
    sgks_cmd_info_s *mdi_normal				= NULL;

    mdi_normal 							= &g_mdi_manager.dsp_buff.cmd_buff.normal_cmd_buffer;
    mdi_normal_buff			  			= g_mdi_manager.dsp_buff.cmd_buff.normal_cmd_buffer.buffer_temp_area;
    dsp_normal_buff			  		    = (u8*)g_mdi_manager.dsp_buff.cmd_buff.normal_cmd_buffer.buffer_addr;

    mdi_cmdq_header           			= &g_mdi_manager.dsp_buff.cmd_buff.normal_cmd_buffer.cmd_head;
    dsp_cmdq_header 					= (sgks_dsp_cmd_header_s *)dsp_normal_buff;




#if 0
    printk("[send dsp normalB 0] dsp_normal_buff cmd num %d  dsp_op_mode 0x%x  cmd_code 0x%x\n"
           ,mdi_cmdq_header->num_cmd
           ,dsp_op_mode
           ,g_mdi_manager.dsp_buff.cmd_buff.cmd_mode);
#endif

    if (mdi_cmdq_header->num_cmd < 0 || mdi_cmdq_header->num_cmd > SGKS_DSP_MAX_CMD_NUM)
    {
        printk("transfer cmd num warning: [%d] \n",mdi_cmdq_header->num_cmd);
    }

    if((mdi_cmdq_header->num_cmd > 0) || (g_mdi_manager.dsp_buff.cmd_buff.cmd_mode == SGKS_MDI_CMD_MODE_BUSY))
    {

#if 1
        if (dsp_op_mode != SGKS_DSP_DECODE_MODE && mdi_cmdq_header->cmd_seq_num > 0)
        {

            if (sgsk_mdi_irq_CheckDspCmdRecvSeq(mdi_cmdq_header->cmd_seq_num) != 1)
            {
                return;
            }

        }
#endif

        mdi_cmdq_header->cmd_seq_num++;

#if 0
        // Copy and flush queue first
        printk("dsp_normal_buff 0x%x  mdi_normal_buff 0x%x mdi_cmdq_header->num_cmd * SGKS_DSP_CMD_SIZE 0x%x, num_cmd %d, cmd_seq_num %d\n"
               ,dsp_normal_buff + sizeof(sgks_dsp_cmd_header_s)
               ,mdi_normal_buff
               ,mdi_cmdq_header->num_cmd * SGKS_DSP_CMD_SIZE
               ,mdi_cmdq_header->num_cmd
               ,mdi_cmdq_header->cmd_seq_num);
#endif

        dsp_cmdq_header->num_cmd 	 = mdi_cmdq_header->num_cmd;
        dsp_cmdq_header->cmd_seq_num = mdi_cmdq_header->cmd_seq_num;
#if 0
        printk("[send dsp normalB 1] dsp_normal_buff num_cmd %d, cmd_seq_num 0x%x cmd_mode 0x%x\n"
               ,dsp_cmdq_header->num_cmd
               ,dsp_cmdq_header->cmd_seq_num
               ,g_mdi_manager.dsp_buff.cmd_buff.cmd_mode);
#endif

        if (dsp_cmdq_header->num_cmd > SGKS_DSP_MAX_CMD_NUM)
        {
            dsp_cmdq_header->num_cmd = SGKS_DSP_MAX_CMD_NUM;
            printk("transfer cmd num warning : cmd num too max\n");
        }

        memcpy(dsp_normal_buff + sizeof(sgks_dsp_cmd_header_s), mdi_normal_buff, dsp_cmdq_header->num_cmd * SGKS_DSP_CMD_SIZE);

        clean_d_cache(dsp_normal_buff, sizeof(sgks_dsp_cmd_header_s) + mdi_cmdq_header->num_cmd * SGKS_DSP_CMD_SIZE);
        mdi_cmdq_header->num_cmd		 	= 0;

        sgks_mdi_CheckDspCmd(dsp_normal_buff, dsp_cmdq_header->num_cmd, dsp_cmdq_header->cmd_seq_num);


    }

//printk("cmd_avail_compl_wait_count %d\n",g_mdi_manager.dsp_compl.cmd_avail_compl_wait_count);
//    if(g_mdi_manager.dsp_compl.cmd_avail_compl_wait_count > 0)
    {
        //      g_mdi_manager.dsp_compl.cmd_avail_compl_wait_count--;
        complete(&g_mdi_manager.dsp_compl.cmd_avail_compl);
    }

}




static void sgks_mdi_irq_transfer_cmd(u32 dsp_op_mode)
{

    unsigned long flag;
    local_irq_save(flag);
    sgks_mdi_cmd_transfer(dsp_op_mode);
    local_irq_restore(flag);
}

static irqreturn_t sgks_mdi_irq_dsp(int irqno, void *dev_id)
{
    void *irq_msg = NULL;
    u32 dsp_op_mode = 0;

    irq_msg  = sgks_mdi_irq_RevcMsg();

    if (irq_msg != NULL)
    {
        dsp_op_mode = *(u32 *)irq_msg;

        if(dsp_op_mode == SGKS_DSP_ENCODE_MODE)
        {
            sgks_mdi_irq_Save_dsp_EncStatus(irq_msg);
            sgks_mdi_irq_isp_update(irq_msg);
			sgks_mdi_irq_Get_yuv_Info(dsp_op_mode,irq_msg);
            if( g_enc_info.init_flag == 1)
            {
                sgks_mdi_irq_parse_encode_msg((encode_msg_t *)irq_msg);
            }
        }
        else if(dsp_op_mode == SGKS_DSP_DECODE_MODE)
        {
            sgks_mdi_irq_Save_dsp_DecStatus(irq_msg);
            sgks_mdi_irq_parse_vdec_msg(irq_msg);
			sgks_mdi_irq_Get_yuv_Info(dsp_op_mode,irq_msg);
        }

        //if( g_mdi_manager.dsp_compl.state_change_compl_wait_count > 0)
        {
            //  g_mdi_manager.dsp_compl.state_change_compl_wait_count--;
            complete(&g_mdi_manager.dsp_compl.state_change_compl);
        }
		
 		// sgks_mdi_StartHighresTimer(TURBO_CMD_DELAY);
    	sgks_mdi_irq_transfer_cmd(dsp_op_mode);

	}

    return IRQ_HANDLED;
	
}



static irqreturn_t sgks_mdi_irq_Vi(int irqno, void *dev_id)
{



    sgks_vi_irq_info_s        *pirqinfo;
    pirqinfo = (sgks_vi_irq_info_s *)dev_id;

    if(pirqinfo->callback)
    {
        pirqinfo->callback(pirqinfo->callback_data, pirqinfo->counter);
    }
    else
    {
        pirqinfo->counter++;
        //printk("pirqinfo->counter %d\n",pirqinfo->counter);
        atomic_set(&pirqinfo->proc_hinfo.sync_proc_flag, 0xFFFFFFFF);
        wake_up_all(&pirqinfo->proc_hinfo.sync_proc_head);
    }


    //dsp_cvbs_in_irq();

    return IRQ_HANDLED;

}

static const struct file_operations sgks_mdi_irq_ops =
{
    .open = sgks_sync_proc_open,
    .read = sgks_sync_proc_read,
    .release = sgks_sync_proc_release,
    .write = sgks_sync_proc_write,
};

static int sgks_mdi_irq_vi_read(char *start, void *data)
{
    sgks_vi_irq_info_s        *pirqinfo;
    pirqinfo = (sgks_vi_irq_info_s *)data;
    return sprintf(start, "%08x", pirqinfo->counter);
}

int sgks_mdi_irq_vi_add(sgks_mdi_manager_s *mdi, unsigned int irq, unsigned long flags, u8 *proc_name, u32 id)
{
    int ret = 0;

    if(id >= sizeof(mdi->vi_irq_list) / sizeof(sgks_vi_irq_info_s))
    {
        printk("vi irq id err: %d!\n", id);
        return -1;
    }

    /*******************init irq info************************/
    mdi->vi_irq_list[id].irq 							= irq;
    mdi->vi_irq_list[id].flags 							= flags;
    mdi->vi_irq_list[id].counter 						= 0;

    mdi->vi_irq_list[id].proc_hinfo.sync_read_proc 		= sgks_mdi_irq_vi_read;
    mdi->vi_irq_list[id].proc_hinfo.sync_read_data 		= &mdi->vi_irq_list[id];
    mdi->vi_irq_list[id].callback_data 					= NULL;
    mdi->vi_irq_list[id].callback 						= NULL;

    snprintf(mdi->vi_irq_list[id].name, sizeof(mdi->vi_irq_list[id].name), "%s", proc_name);
    sgks_sync_proc_hinit(&mdi->vi_irq_list[id].proc_hinfo);

    /*****************request irq**************************/
    if((irq >= VIC_IRQ(0)) && (irq < VIC_IRQ(NR_IRQS)))
    {
        ret = request_irq(irq, sgks_mdi_irq_Vi, flags, mdi->vi_irq_list[id].name, &mdi->vi_irq_list[id]);

        if(ret)
        {
            printk("can't request IRQ(%d)!\n", irq);
            return -1;
        }

        printk(" request vi irq...%d ok-- %s\n", irq, mdi->vi_irq_list[id].name);
    }


    /*****************create proc **************************/
    mdi->vi_irq_list[id].proc_file = create_proc_entry(mdi->vi_irq_list[id].name, S_IRUGO, get_sgks6802_proc_dir());

    if(mdi->vi_irq_list[id].proc_file == NULL)
    {
        mdi->vi_irq_list[id].irq = -1;
        free_irq(irq, &mdi->vi_irq_list[id]);
        printk("can't register vi proc %s!\n", mdi->vi_irq_list[id].name);
        return -1;
    }
    else
    {
        mdi->vi_irq_list[id].proc_file->data = &mdi->vi_irq_list[id].proc_hinfo;
        mdi->vi_irq_list[id].proc_file->proc_fops = &sgks_mdi_irq_ops;
    }

    return 0;

}



void sgks_vi_irq_remove(sgks_vi_irq_info_s *pirqinfo)
{
	if(pirqinfo)
	{
		if((pirqinfo->irq >= VIC_IRQ(0)) &&
		        (pirqinfo->irq < VIC_IRQ(NR_IRQS)))
		{
			free_irq(pirqinfo->irq, pirqinfo);
		}

		if(pirqinfo->proc_file)
			remove_proc_entry(pirqinfo->name,
			                  get_sgks6802_proc_dir());
	}
}



static int sgks_mdi_ioc_ClearIrq(sgks_mdi_manager_s *mdi)
{

	int i =0;
	
    /*********vcore irq*********/
	free_irq(VCORE_IRQ, &sgks_mdi_cdev);
	
	/*********vin irq*********/
	for (i=0; i<MAX_VI_IRQ_NUM; i++)
	{
          free_irq(mdi->vi_irq_list[i].irq, &mdi->vi_irq_list[i]);

		  if (mdi->vi_irq_list[i].proc_file)
		  {
			remove_proc_entry(mdi->vi_irq_list[i].name, get_sgks6802_proc_dir());
		  }
	}

    return 0;

}

static int sgks_mdi_ioc_SetupIrq(sgks_mdi_manager_s *mdi)
{

    /**************************** dsp *************************/
    int ret = request_irq(VCORE_IRQ, sgks_mdi_irq_dsp, IRQF_TRIGGER_RISING | IRQF_DISABLED | IRQF_SHARED, "encode_core", &sgks_mdi_cdev);

    if(ret < 0)
    {
        printk("setup irq %d for dsp2 failed\n", VCORE_IRQ);
        return ret;
    }

    printk("setup irq %d for dsp2 ok\n", VCORE_IRQ);


    /**************************** vin *************************/
    ret = sgks_mdi_irq_vi_add(mdi, VI_IRQ, IRQF_TRIGGER_RISING, "video_sync", 0);

    if(ret < 0)
    {
        printk("setup irq %d for VI_IRQ failed\n", VI_IRQ);
        return ret;
    }

    ret = sgks_mdi_irq_vi_add(mdi, -1, 0, "video_video", 1);

    if(ret < 0)
    {
        printk("setup irq  for video_video failed\n");
        return ret;
    }

    ret = sgks_mdi_irq_vi_add(mdi, ICORE_LAST_PIXEL_IRQ, IRQF_TRIGGER_RISING, "video_frame_last_pixel", 2);

    if(ret < 0)
    {
        printk("setup irq %d for ICORE_LAST_PIXEL_IRQ failed\n", ICORE_LAST_PIXEL_IRQ);
        return ret;
    }

    ret = sgks_mdi_irq_vi_add(mdi, ICORE_SENSOR_VSYNC_IRQ, IRQF_TRIGGER_RISING, "video_frame", 3);

    if(ret < 0)
    {
        printk("setup irq %d for ICORE_SENSOR_VSYNC_IRQ failed\n", ICORE_SENSOR_VSYNC_IRQ);
        return ret;
    }

    return SGKS_SUCCESS;

}



static int sgks_mdi_ioc_WaitDspStatus(sgks_mdi_dsp_status_s *dsp_status)
{
    unsigned long flags;
    unsigned long leavetime;
    int ret = 0;
    int err_count = 0;

#if 1
    printk("wait dsp status : dsp_status->op_mode[%d] , dsp_status->op_sub_mode[%d] dsp_status->state [%d]\n"
           ,dsp_status->op_mode
           ,dsp_status->op_sub_mode
           ,dsp_status->state);
#endif
#if 0
    printk("wait dsp status val : dsp_status->op_mode[%d] , dsp_status->op_sub_mode[%d] dsp_status->state [%d]\n"
           ,g_mdi_manager.dsp_status.op_mode
           ,g_mdi_manager.dsp_status.op_sub_mode
           ,g_mdi_manager.dsp_status.state);

#endif

    while(1)
    {

        msleep(10);

        //local_irq_save(flags);

        if(
            ((dsp_status->op_mode == -1) || (dsp_status->op_mode != -1 && dsp_status->op_mode == g_mdi_manager.dsp_status.op_mode))
            && ((dsp_status->op_sub_mode == -1) || (dsp_status->op_sub_mode != -1 && dsp_status->op_sub_mode == g_mdi_manager.dsp_status.op_sub_mode))
            && ((dsp_status->state == -1) || (dsp_status->state != -1 && dsp_status->state == g_mdi_manager.dsp_status.state))
        )
        {
#if 1
            printk("wait dsp status done: dsp_status->op_mode[%d] , dsp_status->op_sub_mode[%d] dsp_status->state [%d]\n"
                   ,dsp_status->op_mode
                   ,dsp_status->op_sub_mode
                   ,dsp_status->state);
#endif

            //local_irq_restore(flags);

            break;
        }

        g_mdi_manager.dsp_compl.state_change_compl_wait_count++;

        //local_irq_restore(flags);


        WAIT_FOR_COMPL_TIMEOUT("state_change_compl", &g_mdi_manager.dsp_compl.state_change_compl, 10 * HZ, &ret);
        if (ret != SGKS_SUCCESS)
        {
            printk("wait dsp status err1: dsp_status->op_mode[%d] , dsp_status->op_sub_mode[%d] dsp_status->state [%d]\n"
                   ,dsp_status->op_mode
                   ,dsp_status->op_sub_mode
                   ,dsp_status->state);
            return SGKS_FAIL;
        }

        if (err_count >= 2000)
        {

            printk("wait dsp status err2: dsp_status->op_mode[%d] , dsp_status->op_sub_mode[%d] dsp_status->state [%d]\n"
                   ,dsp_status->op_mode
                   ,dsp_status->op_sub_mode
                   ,dsp_status->state);

            return SGKS_FAIL;
        }

        err_count++;

    }


    return SGKS_SUCCESS;

}


static int sgks_mdi_ioc_GetDspStatus(sgks_mdi_dsp_status_s *dsp_status)
{
    unsigned long flags;
    unsigned long leavetime;

    local_irq_save(flags);

    memcpy(dsp_status, &g_mdi_manager.dsp_status, sizeof(sgks_mdi_dsp_status_s));

    //printk("get dsp status done: dsp_status->op_mode[0x%x] , dsp_status->state [0x%x]\n", dsp_status->op_mode, dsp_status->state);

    local_irq_restore(flags);

    return SGKS_SUCCESS;

}


static int sgks_mdi_ioc_SetCmdMode(char *cmd_mode)
{

    int ret = -1;
    sgks_cmd_info_s *mdi_default_cmd_buff  = NULL;
    sgks_dsp_cmd_header_s *cmdq_header      = NULL;
    sgks_cmd_buffer_config_s *mdi_cmd  = &g_mdi_manager.dsp_buff.cmd_buff;

    u32 mode = *cmd_mode;

    switch(mode)
    {

    case SGKS_MDI_CMD_MODE_DEFAULT_LOADING:
    {
        mdi_default_cmd_buff  = &g_mdi_manager.dsp_buff.cmd_buff.default_cmd_buffer;
        cmdq_header           = &mdi_default_cmd_buff->cmd_head;
        invalidate_d_cache(mdi_default_cmd_buff->buffer_addr, mdi_default_cmd_buff->buffer_size);
        printk("default cmd inv 0x%x, 0x%x\n",mdi_default_cmd_buff->buffer_addr,mdi_default_cmd_buff->buffer_size);
        ret = 0;
        break;
    }

    case SGKS_MDI_CMD_MODE_DEFAULT_READY:
    {
        mdi_default_cmd_buff  = &g_mdi_manager.dsp_buff.cmd_buff.default_cmd_buffer;

        cmdq_header           = &mdi_default_cmd_buff->cmd_head;

        memcpy(mdi_default_cmd_buff->buffer_addr, &mdi_default_cmd_buff->cmd_head, sizeof(sgks_dsp_cmd_header_s));
        clean_d_cache((void *)mdi_default_cmd_buff->buffer_addr, sizeof(sgks_dsp_cmd_header_s) + cmdq_header->num_cmd * SGKS_MDI_CMD_SIZE);
        //sgks_mdi_ioc_DumpMemToFile("/home/dd-def-fw", sgks6802_virt_to_phys(mdi_default_cmd_buff->buffer_addr), 0x1000);

		cmdq_header->num_cmd = 0;

        ret = 0;

        break;
    }

    case SGKS_MDI_CMD_MODE_BLOCK_LOADING:
    {
        /*normal ---> block*/
        if (mdi_cmd->cmd_mode == SGKS_MDI_CMD_MODE_NORMAL_LOADING)
        {
            ret = sgks_mdi_WaitSendToDspNormalCmdBuff();
        }
        else
        {
            ret = 0;
        }
        break;
    }

    case SGKS_MDI_CMD_MODE_BLOCK_READY:
    {
        ret = sgks_mdi_sendBlockcmd();
        break;
    }

    case SGKS_MDI_CMD_MODE_NORMAL_LOADING:
    {
		sgks_mdi_sendBlockOccupyCmd();
        ret = 0;
        break;
    }

    case SGKS_MDI_CMD_MODE_VDEC_NORMAL_LOADING:
    {
        ret = 0;
        break;
    }

    case SGKS_MDI_CMD_MODE_NORMAL_READY:
    {
        ret = 0;
        break;
    }

    case SGKS_MDI_CMD_MODE_BUSY:
    {
        ret = 0;
        break;
    }

    default:
    {
        mdi_error("cmd mode set err! id 0x%x\n",mode);
        ret = -1;
        break;
    }

    }


    if (ret == 0)
    {

        memcpy(&mdi_cmd->cmd_mode, cmd_mode, sizeof(sgks_mdi_cmd_mode_e));
        printk("set cmd mode ok 0x%x\n",mdi_cmd->cmd_mode);
    }

    return ret;

}


static int sgks_mdi_ioc_sendcmd(char *dsp_cmd, int dsp_cmd_size)
{
    sgks_cmd_buffer_config_s *mdi_cmd_buff  = &g_mdi_manager.dsp_buff.cmd_buff;
    int ret = 0;

	//printk("send cmd code 0x%x\n",*(u32*)dsp_cmd);

    switch(mdi_cmd_buff->cmd_mode)
    {
    case SGKS_MDI_CMD_MODE_NONE:
        break;

    case SGKS_MDI_CMD_MODE_BUSY:
        break;

    case SGKS_MDI_CMD_MODE_DEFAULT_LOADING:
        ret = sgks_mdi_sendDefaultcmd(dsp_cmd, dsp_cmd_size);
        break;

    case SGKS_MDI_CMD_MODE_BLOCK_LOADING:
        ret = sgks_mdi_saveBlockcmd(dsp_cmd, dsp_cmd_size);
        break;

    case SGKS_MDI_CMD_MODE_NORMAL_LOADING:
		ret = sgks_mdi_sendNormalcmd(dsp_cmd, dsp_cmd_size);
        break;
		
    case SGKS_MDI_CMD_MODE_BLOCK_READY:
		ret = sgks_mdi_WaitSendToDspNormalCmdBuff();
        ret = sgks_mdi_sendNormalcmd(dsp_cmd, dsp_cmd_size);
        break;

    case SGKS_MDI_CMD_MODE_VDEC_NORMAL_LOADING:
        //ret = sgks_mdi_sendVdecNormalcmd(dsp_cmd, dsp_cmd_size);
        ret = sgks_mdi_sendNormalcmd(dsp_cmd, dsp_cmd_size);
        break;

    default:
        mdi_error("!!CMD MODE ERRORL: 0x%x!!\n",mdi_cmd_buff->cmd_mode);
        ret = SGKS_OPERATION_ERR_CMDMODE;
        break;

    }

    return ret;

}

int sgks_mdi_ioc_GetIspStatistics(sgks_mdi_isp_statistics_pos_s *isp_statistics_pos)
{
    int ret = 0;
    WAIT_FOR_COMPL_TIMEOUT("isp_statis_compl", &g_mdi_manager.dsp_compl.isp_statis_compl, 10 * HZ, &ret);
    if (ret != SGKS_SUCCESS)
    {
        return -1;
    }

#if 0
    printk("isp_rgb_aaa_ptr_pos %d isp_cfa_aaa_ptr_pos %d isp_hist_aaa_ptr_pos %d \n"
           ,g_mdi_manager.isp_user_statistics_pos.isp_rgb_aaa_ptr_pos
           ,g_mdi_manager.isp_user_statistics_pos.isp_cfa_aaa_ptr_pos
           ,g_mdi_manager.isp_user_statistics_pos.isp_hist_aaa_ptr_pos);
#endif

    memcpy(isp_statistics_pos, &g_mdi_manager.isp_user_statistics_pos, sizeof(sgks_mdi_isp_statistics_pos_s));

    return SGKS_SUCCESS;

}


int sgks_mdi_ioc_GetYuvData(sgks_mdi_yuv_info_s *yuv_data)
{
    int ret = 0;
	
    memcpy(yuv_data, &g_mdi_manager.user_yuv_info, sizeof(sgks_mdi_yuv_info_s));

    return SGKS_SUCCESS;

}


int sgks_mdi_ioc_WaitCompletion(sgks_mdi_wait_completion_s *completion)
{
    int ret = 0;

    unsigned long flags;
    struct completion *p_complt = NULL;
    char *p_complt_name = NULL;
    int wati_cmd = 0;

    sgks_dsp_cmd_header_s *mdi_cmdq_header = &g_mdi_manager.dsp_buff.cmd_buff.normal_cmd_buffer.cmd_head;

    //printk("==start===wait completion type 0x%x\n",completion->completion);

    switch(completion->completion)
    {

    case SGKS_COMPLETION_ISP_COMPL:
    {
        p_complt 		= &g_mdi_manager.dsp_compl.isp_statis_compl;
        p_complt_name 	= "isp_statis_compl";
        break;
    }

    case SGKS_COMPLETION_CMD_AVAIL_COMPL:
    {
        p_complt = &g_mdi_manager.dsp_compl.cmd_avail_compl;
        p_complt_name 	= "cmd_avail_compl";
        wati_cmd = 1;
        break;
    }

    case SGKS_COMPLETION_DECODE_COMPL:
    {
        p_complt = &g_mdi_manager.dsp_compl.decode_compl;
        p_complt_name 	= "decode_compl";
        break;
    }

    case SGKS_COMPLETION_STATE_CHANGE_COMPL:
    {
        p_complt = &g_mdi_manager.dsp_compl.state_change_compl;
        p_complt_name 	= "state_change_compl";
        break;
    }


    default:
    {
        printk("completion type err!\n");
        return SGKS_FAIL;
    }

    }

    while(1)
    {

        msleep(1);

        local_irq_save(flags);


        if(wati_cmd == 1 && mdi_cmdq_header->num_cmd == 0)
        {
            local_irq_restore(flags);
            break;
        }


        local_irq_restore(flags);

        WAIT_FOR_COMPL_TIMEOUT(p_complt_name, p_complt, 10 * HZ, &ret);
        if (ret == SGKS_SUCCESS)
        {
            break;
        }
        else
        {
            return SGKS_FAIL;
        }

    }


    //printk("==end===wait completion type 0x%x name %s\n",completion->completion,p_complt_name);

    return SGKS_SUCCESS;

}

static int sgks_mdi_ioc_SetEncode()
{


    sgks_bitsteam_buffer_info_s *bsb_buff_info = &g_mdi_manager.dsp_buff.bsb_info;
    memset(&g_enc_info, 0x00, sizeof(sgks_mdi_encode_info_s));
    
    sema_init(&(g_enc_info.sem_frame_counter), 0);
    g_enc_info.total_pic_encoded_h264_mode = 0;
    g_enc_info.total_pic_encoded_mjpeg_mode = 0;
    g_enc_info.total_pic_encoded_jpeg_mode = 0;
    g_enc_info.h264_pic_counter = 0;
    g_enc_info.mjpeg_pic_counter = 0;
    g_enc_info.total_pic_counter = 0;
    g_enc_info.jpeg_pic_counter = 0;
    
    g_enc_info.bits_desc_start = (sgks_dsp_bits_info_s *)bsb_buff_info->bs_desc_kernel_start;
    g_enc_info.bits_desc_end = (sgks_dsp_bits_info_s *)bsb_buff_info->bs_desc_kernel_start + NUM_BS_DESC;
    g_enc_info.bits_desc_read_ptr = (sgks_dsp_bits_info_s *)bsb_buff_info->bs_desc_kernel_start;
    g_enc_info.bits_desc_prefetch_ptr = (sgks_dsp_bits_info_s *)bsb_buff_info->bs_desc_kernel_start;
    
    g_enc_info.sem_frame_counter.count = 0;

    g_enc_info.init_flag = 1;
    mutex_init(&g_enc_info.bsb_mem_mutex);

    DEBUGMSG(ZONE_VENC, ("%s end\n", __FUNCTION__));
    return SGKS_SUCCESS;
}

int sgks_mdi_ioc_GetVdecBuffPos(sgks_mdi_vdec_buff_pos_s *vdec_buff_info)
{

    unsigned long flags;
    int ret = 0;

    local_irq_save(flags);
    memcpy(vdec_buff_info, &g_mdi_manager.vdec_buff_pos, sizeof(sgks_mdi_vdec_buff_pos_s));
    local_irq_restore(flags);

    g_mdi_manager.dsp_compl.decode_compl_wait_count++;
    WAIT_FOR_COMPL_TIMEOUT("decode_compl", &g_mdi_manager.dsp_compl.decode_compl, 10 * HZ, &ret);
    if (ret != SGKS_SUCCESS)
    {
        return -1;
    }

    return SGKS_SUCCESS;

}


int sgks_mdi_ioc_GetVdecInfo(sgks_mdi_vdec_decode_info_s *vdec_info)
{

    unsigned long flags;
    int ret = 0;

    local_irq_save(flags);
    memcpy(vdec_info, &g_mdi_manager.vdec_info, sizeof(sgks_mdi_vdec_decode_info_s));
    local_irq_restore(flags);


    return SGKS_SUCCESS;

}


static int sgks_mdi_ioc_WaitYuv2EncComplete(u32 msecs)
{
    int ret = SGKS_SUCCESS;
    WAIT_FOR_COMPL_TIMEOUT("yuv_to_enc_compl", &g_mdi_manager.dsp_compl.yuv_to_enc_compl, msecs_to_jiffies(msecs), &ret);
    if (ret != SGKS_SUCCESS)
    {
        g_mdi_manager.dsp_compl.yuv_to_enc_compl_wait_count--;
        return SGKS_FAIL;
    }         
    return SGKS_SUCCESS;
}

static int sgks_mdi_ioc_malloc(struct file *filp, sgks_mdi_mem_s *meminfo)
{
    u32 kernel_addr;
    if(meminfo == NULL)
    {
        printk("Error: meminfo pointer is NULL\n");
        return EINVAL;
    }

    //must page alignment
    meminfo->size = meminfo->size % PAGE_SIZE ? ((meminfo->size / PAGE_SIZE) + 1) * PAGE_SIZE : meminfo->size;
    kernel_addr = kmalloc(meminfo->size, GFP_KERNEL);
    if(kernel_addr == NULL)
    {
        printk("Error: out of memory:%d\n", meminfo->size);
        return -ENOMEM;
    }

    meminfo->phy_addr = (u8 *)virt_to_phys(kernel_addr);

    down_write(&current->mm->mmap_sem);
    g_mdi_manager.user_area.user_mmap.mmap_phy_start_addr = meminfo->phy_addr;
    g_mdi_manager.user_area.user_mmap.mmap_phy_size = meminfo->size;
    meminfo->user_addr = do_mmap(filp, 0, meminfo->size, PROT_READ | PROT_WRITE, MAP_SHARED, 0);
    up_write(&current->mm->mmap_sem);

    if(meminfo->user_addr > 0xC0000000)
    {
        return -ENOMEM;
    }

    return SGKS_SUCCESS;

}

static int sgks_mdi_ioc_free(struct file *filp, sgks_mdi_mem_s *meminfo)
{
    int ret;

    if(meminfo == NULL)
    {
        printk("Error: meminfo pointer is NULL\n");
        return EINVAL;
    }

    down_write(&current->mm->mmap_sem);
    ret = do_munmap(current->mm, (unsigned long)meminfo->user_addr, meminfo->size);
    up_write(&current->mm->mmap_sem);

    if(ret < 0)
    {
        printk("Error:%s do_munmap:%d\n", __func__, ret);
        return ret;
    }

    kfree(phys_to_virt(meminfo->phy_addr));


    return SGKS_SUCCESS;


}

static long sgks_mdi_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
{
    int ret = SGKS_FAIL;
    int err_count = 0;
    msg_t ioctl_msg;
    int copy_user = 0;



    switch(cmd)
    {

    case SGKS_MDI_IOCTL_OPERATION:
    {

        ret = copy_from_user(&ioctl_msg, (msg_t __user *)args, sizeof(msg_t)) ? -EFAULT : SGKS_SUCCESS;

        if(ret != SGKS_SUCCESS)
        {
            ret = SGKS_OPERATION_ERR_DATA;
            break;
        }


        //printk("------start-------mdi ioctl 0x%x\n",ioctl_msg.msg_head.msg_type);

        switch(ioctl_msg.msg_head.msg_type)
        {

        case SGKS_MDI_OPERATION_MMAP:
        {
            sgks_user_param_s *mdi_manager_user;
            sgks_mdi_mmap_s *mmap;
            CHECK_PARAM_SIZE("sgks_mdi_mmap_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_mmap_s),SGKS_FAIL);

            down_write(&current->mm->mmap_sem);
            mdi_manager_user               = &g_mdi_manager.user_area;
            mmap                           = (sgks_mdi_mmap_s *)ioctl_msg.msg_data;
            mdi_manager_user->user_mmap.mmap_phy_start_addr = mmap->mmap_phy_start_addr;
            mdi_manager_user->user_mmap.mmap_phy_size       = mmap->mmap_phy_size;
            CHECK_NULL_POINTER(mmap->mmap_phy_start_addr,SGKS_FAIL);
            unsigned long maddr = do_mmap(mdi_manager_user->file, 0, mmap->mmap_phy_size, PROT_READ | PROT_WRITE, MAP_SHARED, 0);
            up_write(&current->mm->mmap_sem);

            if(ret & ~PAGE_MASK)
            {
                ret = SGKS_FAIL;
                break;
            }
            else
            {
                ret = SGKS_SUCCESS;
            }

            //printk("SGKS_MDI_OPERATION_MMAP,[0x%x] ---> [0x%x]\n",mmap->mmap_phy_start_addr,maddr);

            memset(ioctl_msg.msg_data, 0, sizeof(ioctl_msg.msg_data));
            mmap->mmap_user_start_addr = (u8 *)maddr;
            mmap->mmap_user_size       = mdi_manager_user->user_mmap.mmap_phy_size;
            copy_user = 1;
            break;
        }

        case SGKS_MDI_OPERATION_UNMMAP:
        {
            CHECK_PARAM_SIZE("sgks_mdi_mmap_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_mmap_s),SGKS_FAIL);
            sgks_mdi_mmap_s *mmap                           = (sgks_mdi_mmap_s *)ioctl_msg.msg_data;

            //printk("SGKS_MDI_OPERATION_UNMMAP 0x%x -- %d\n",mmap->mmap_user_start_addr,mmap->mmap_user_size);

            if (mmap->mmap_user_start_addr == NULL )
            {
                ret = SGKS_FAIL;
                break;
            }

            down_write(&current->mm->mmap_sem);
            unsigned long maddr = do_munmap(current->mm, (unsigned long)mmap->mmap_user_start_addr,(size_t)mmap->mmap_user_size);
            up_write(&current->mm->mmap_sem);

            //if(maddr == 0)
            //{
                //printk("SGKS_MDI_OPERATION_UNMMAP  OK!\n");
            //}


            ret = (maddr == 0) ? SGKS_SUCCESS : SGKS_FAIL;

            break;

        }

        case SGKS_MDI_OPERATION_GETPAGESIZE:
        {

            CHECK_PARAM_SIZE("sgks_get_pagesize_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_get_pagesize_s),SGKS_FAIL);
            memset(ioctl_msg.msg_data, 0, sizeof(ioctl_msg.msg_data));
            sgks_get_pagesize_s *kernelPage = ioctl_msg.msg_data;
            kernelPage->page_size = PAGE_SIZE;
            copy_user = 1;
            ret = SGKS_SUCCESS;
            break;
        }

        case SGKS_MDI_OPERATION_GET_ISP_STATISTICS:
        {

            CHECK_PARAM_SIZE("sgks_mdi_isp_statistics_pos_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_isp_statistics_pos_s),SGKS_FAIL);
            memset(ioctl_msg.msg_data, 0, sizeof(ioctl_msg.msg_data));

            ret = sgks_mdi_ioc_GetIspStatistics((sgks_mdi_isp_statistics_pos_s *)ioctl_msg.msg_data);

            copy_user = 1;
            break;
        }

        case SGKS_MDI_OPERATION_GET_VDEC_BUFF_POS:
        {

            CHECK_PARAM_SIZE("sgks_mdi_vdec_buff_pos_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_vdec_buff_pos_s),SGKS_FAIL);
            memset(ioctl_msg.msg_data, 0, sizeof(ioctl_msg.msg_data));

            ret = sgks_mdi_ioc_GetVdecBuffPos((sgks_mdi_vdec_buff_pos_s *)ioctl_msg.msg_data);

            copy_user = 1;
            break;
        }

        case SGKS_MDI_OPERATION_GET_VDEC_INFO:
        {

            CHECK_PARAM_SIZE("sgks_mdi_vdec_decode_info_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_vdec_decode_info_s),SGKS_FAIL);
            memset(ioctl_msg.msg_data, 0, sizeof(ioctl_msg.msg_data));

            ret = sgks_mdi_ioc_GetVdecInfo((sgks_mdi_vdec_decode_info_s *)ioctl_msg.msg_data);

            copy_user = 1;
            break;
        }

        case SGKS_MDI_OPERATION_SET_VDEC_BUFF_INFO:
        {

            CHECK_PARAM_SIZE("sgks_mdi_vdec_buff_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_vdec_buff_s),SGKS_FAIL);

            sgks_mdi_vdec_buff_s *user_vdec_buff = (sgks_mdi_vdec_buff_s *)ioctl_msg.msg_data;

            g_mdi_manager.vdec_buff.buff_phy		= user_vdec_buff->buff_phy;
            g_mdi_manager.vdec_buff.buff_size 	= user_vdec_buff->buff_size;

            ret = SGKS_SUCCESS;
            copy_user = 1;
            break;
        }

        case SGKS_MDI_OPERATION_SETISPBUFFER:
        {

            CHECK_PARAM_SIZE("sgks_isp_buffer_config_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_isp_buffer_config_s),SGKS_FAIL);

            sgks_isp_buffer_config_s   *isp_buff               			= (sgks_isp_buffer_config_s *)ioctl_msg.msg_data;
            sgks_isp_buffer_config_s   *mdi_isp_buff  						= &g_mdi_manager.isp_buff;
            sgks_mdi_isp_statistics_s  *mdi_isp_statistics 				= &g_mdi_manager.isp_statistics;
            sgks_mdi_isp_statistics_pos_s  *mdi_isp_statistics_pos 		= &g_mdi_manager.isp_user_statistics_pos;

            /*isp statistics buff*/
            mdi_isp_buff->isp_aaa_fifo1_base 				     	= sgks6802_phys_to_virt(isp_buff->isp_aaa_fifo1_base);
            mdi_isp_buff->isp_aaa_fifo1_base_size			     	= sgks6802_phys_to_virt(isp_buff->isp_aaa_fifo1_base_size);
            memset(mdi_isp_buff->isp_aaa_fifo1_base, 0, mdi_isp_buff->isp_aaa_fifo1_base_size);

            mdi_isp_buff->isp_aaa_fifo2_base 				     	= sgks6802_phys_to_virt(isp_buff->isp_aaa_fifo2_base);
            mdi_isp_buff->isp_aaa_fifo2_base_size 				 	= sgks6802_phys_to_virt(isp_buff->isp_aaa_fifo2_base_size);
            memset(mdi_isp_buff->isp_aaa_fifo2_base, 0, mdi_isp_buff->isp_aaa_fifo2_base_size);

            /*isp statistics ptr*/
            mdi_isp_statistics->isp_rgb_aaa_ptr_next 	= mdi_isp_buff->isp_aaa_fifo1_base;
            mdi_isp_statistics->isp_cfa_aaa_ptr_next 	= mdi_isp_buff->isp_aaa_fifo2_base;

            /*isp statistics ptr pos*/
            memset(mdi_isp_statistics_pos, 0, sizeof(sgks_mdi_isp_statistics_pos_s));

            ret = SGKS_SUCCESS;

            break;

        }


        case SGKS_MDI_OPERATION_SETDSPBUFFER:
        {

            CHECK_PARAM_SIZE("sgks_dsp_buffer_config_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_dsp_buffer_config_s),SGKS_FAIL);

            memset(&g_mdi_manager.dsp_buff.cmd_buff, 0, sizeof(sgks_cmd_buffer_config_s));
            memset(&g_mdi_manager.dsp_buff.result_queue, 0, sizeof(sgks_result_queue_buffer_s));
            memset(&g_mdi_manager.dsp_buff.dsp2_info, 0, sizeof(sgks_dsp2_info_buffer_s));
            memset(&g_mdi_manager.dsp_buff.bsb_info, 0, sizeof(sgks_bitsteam_buffer_info_s));


            sgks_cmd_buffer_config_s   *mdi_cmd_buff  				= &g_mdi_manager.dsp_buff.cmd_buff;
            sgks_result_queue_buffer_s *mdi_result_queue_buff  	= &g_mdi_manager.dsp_buff.result_queue;
            sgks_dsp2_info_buffer_s    *mdi_dsp2_info              = &g_mdi_manager.dsp_buff.dsp2_info;
            sgks_bitsteam_buffer_info_s *mdi_bitstream_buff_info   = &g_mdi_manager.dsp_buff.bsb_info;
			sgks_cap_info_buffer_s     *mdi_cap_buff_info   = &g_mdi_manager.dsp_buff.cap_info;
            sgks_dsp_buffer_config_s   *dsp_buff               	= (sgks_dsp_buffer_config_s *)ioctl_msg.msg_data;

            mdi_cmd_buff->default_cmd_buffer.buffer_addr = sgks6802_phys_to_virt(dsp_buff->cmd_buff.default_cmd_buffer.buffer_addr);
            mdi_cmd_buff->default_cmd_buffer.buffer_size = dsp_buff->cmd_buff.default_cmd_buffer.buffer_size;
            memset(mdi_cmd_buff->default_cmd_buffer.buffer_addr, 0, mdi_cmd_buff->default_cmd_buffer.buffer_size);

            mdi_cmd_buff->normal_cmd_buffer.buffer_addr = sgks6802_phys_to_virt(dsp_buff->cmd_buff.normal_cmd_buffer.buffer_addr);
            mdi_cmd_buff->normal_cmd_buffer.buffer_size = dsp_buff->cmd_buff.normal_cmd_buffer.buffer_size;
            memset(mdi_cmd_buff->normal_cmd_buffer.buffer_addr, 0, mdi_cmd_buff->normal_cmd_buffer.buffer_size);

            mdi_bitstream_buff_info->bsb_phy_start = dsp_buff->bsb_info.bsb_phy_start;
            mdi_bitstream_buff_info->bsb_user_start = dsp_buff->bsb_info.bsb_user_start;
            mdi_bitstream_buff_info->bsb_kernel_start = sgks6802_phys_to_virt(dsp_buff->bsb_info.bsb_phy_start);
            mdi_bitstream_buff_info->bsb_size = dsp_buff->bsb_info.bsb_size;

            mdi_bitstream_buff_info->bs_desc_phy_start = dsp_buff->bsb_info.bs_desc_phy_start;
            mdi_bitstream_buff_info->bs_desc_user_start = dsp_buff->bsb_info.bs_desc_user_start;
            mdi_bitstream_buff_info->bs_desc_kernel_start = sgks6802_phys_to_virt(dsp_buff->bsb_info.bs_desc_phy_start);
            mdi_bitstream_buff_info->bs_desc_size = dsp_buff->bsb_info.bs_desc_size;
            
            DEBUGMSG(ZONE_VENC, ("%s bsb phy_addr=0x%x, user_start=0x%x, kernel_start=0x%x, size=0x%x\n",
                                  __FUNCTION__,
                                  mdi_bitstream_buff_info->bsb_phy_start,
                                  mdi_bitstream_buff_info->bsb_user_start,
                                  mdi_bitstream_buff_info->bsb_kernel_start,
                                  mdi_bitstream_buff_info->bsb_size));

            DEBUGMSG(ZONE_VENC, ("%s bs_desc phy_addr=0x%x, user_start=0x%x, kernel_start=0x%x, size=0x%x\n",
                                  __FUNCTION__,
                                  mdi_bitstream_buff_info->bs_desc_phy_start,
                                  mdi_bitstream_buff_info->bs_desc_user_start,
                                  mdi_bitstream_buff_info->bs_desc_kernel_start,
                                  mdi_bitstream_buff_info->bs_desc_size));
			
			mdi_cap_buff_info->cap_info_ptr 	= dsp_buff->cap_info.cap_info_ptr;
			mdi_cap_buff_info->cap_info_ptr_size = dsp_buff->cap_info.cap_info_ptr_size;

            void *ptr 	= NULL;
            u32 err_no = 0;
            if((ptr = kzalloc(sizeof(char) * mdi_cmd_buff->normal_cmd_buffer.buffer_size, GFP_KERNEL)) == NULL)
            {
                printk("malloc dsp tmp buf err1!\n");
                err_no++;
            }

            mdi_cmd_buff->normal_cmd_buffer.buffer_temp_area = ptr;

            if((ptr = kzalloc(sizeof(char) * mdi_cmd_buff->normal_cmd_buffer.buffer_size, GFP_KERNEL)) == NULL)
            {
                printk("malloc dsp tmp buf err2!\n");
                err_no++;
            }

            mdi_cmd_buff->block_cmd_buffer.buffer_temp_area = ptr;

			if((ptr = kzalloc(sizeof(char) * mdi_cmd_buff->normal_cmd_buffer.buffer_size, GFP_KERNEL)) == NULL)
            {
                printk("malloc dsp tmp buf err3!\n");
                err_no++;
            }

            mdi_cmd_buff->block_occupy_buffer.buffer_temp_area = ptr;


            mdi_result_queue_buff->dsp_result_queue_start			= sgks6802_phys_to_virt(dsp_buff->result_queue.dsp_result_queue_start);
            mdi_result_queue_buff->dsp_result_queue_ptr				= sgks6802_phys_to_virt(dsp_buff->result_queue.dsp_result_queue_start);
            mdi_result_queue_buff->dsp_result_queue_end				= sgks6802_phys_to_virt(dsp_buff->result_queue.dsp_result_queue_end);
            mdi_result_queue_buff->dsp_result_queue_size			= dsp_buff->result_queue.dsp_result_queue_size;
            memset(mdi_result_queue_buff->dsp_result_queue_start, 0, mdi_result_queue_buff->dsp_result_queue_size);

            mdi_dsp2_info->dsp2_info_ptr							= sgks6802_phys_to_virt(dsp_buff->dsp2_info.dsp2_info_ptr);

            printk("set dsp_result_queue_ptr v 0x%x, queue_start 0x%x queue_end  0x%x size %d ok!\n"
                   ,mdi_result_queue_buff->dsp_result_queue_ptr
                   ,mdi_result_queue_buff->dsp_result_queue_start
                   ,mdi_result_queue_buff->dsp_result_queue_end
                   ,mdi_result_queue_buff->dsp_result_queue_size);

            printk("set default cmd v 0x%x, size %d ok!\n",mdi_cmd_buff->default_cmd_buffer.buffer_addr,mdi_cmd_buff->default_cmd_buffer.buffer_size);
            printk("set normal cmd  v 0x%x, size %d ok!\n",mdi_cmd_buff->normal_cmd_buffer.buffer_addr,mdi_cmd_buff->normal_cmd_buffer.buffer_size);

            ret = (err_no == 0) ? SGKS_SUCCESS : SGKS_FAIL;

            break;
        }

        case SGKS_MDI_OPERATION_SETCMDMODE:
        {
            CHECK_PARAM_SIZE("sgks_mdi_cmd_mode_e", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_cmd_mode_e),SGKS_FAIL);
            if ( g_mdi_manager.dsp_status.op_mode != SGKS_DSP_DECODE_MODE)
            {
                sgks_mdi_cmd_lock();
            }

            ret =  sgks_mdi_ioc_SetCmdMode(ioctl_msg.msg_data);

            if ( g_mdi_manager.dsp_status.op_mode != SGKS_DSP_DECODE_MODE)
            {
                sgks_mdi_cmd_unlock();
            }
            break;
        }

        case SGKS_MDI_OPERATION_GETDSPSTATUS:
        {
            CHECK_PARAM_SIZE("sgks_mdi_dsp_status_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_dsp_status_s),SGKS_FAIL);
            ret = sgks_mdi_ioc_GetDspStatus((sgks_mdi_dsp_status_s *)ioctl_msg.msg_data);
            break;
        }

        case SGKS_MDI_OPERATION_WAITDSPSTATUS:
        {
            CHECK_PARAM_SIZE("sgks_mdi_dsp_status_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_dsp_status_s),SGKS_FAIL);
            ret = sgks_mdi_ioc_WaitDspStatus((sgks_mdi_dsp_status_s *)ioctl_msg.msg_data);
            break;
        }

        case SGKS_MDI_OPERATION_SETUPIRQ:
        {
            //sgks_mdi_InitHighresTimer(sgks_mdi_irq_transfer_cmd);

            ret = sgks_mdi_ioc_SetupIrq(&g_mdi_manager);

            break;
        }

		case SGKS_MDI_OPERATION_CLEARUPIRQ:
        {
         
            ret = sgks_mdi_ioc_ClearIrq(&g_mdi_manager);

            break;
        }

        case SGKS_MDI_OPERATION_DEBUG_CAPDSPLOG:
        {
            CHECK_PARAM_SIZE("sgks_cap_dsp_log_file_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_cap_dsp_log_file_s),SGKS_FAIL);
            ret = gks_mdi_ioc_log_CapStart(ioctl_msg.msg_data);
            break;
        }

        case SGKS_MDI_OPERATION_DEBUG_DUMPMEMTOFILE:
        {
            CHECK_PARAM_SIZE("sgks_cmd_dump_mem_file_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_cmd_dump_mem_file_s),SGKS_FAIL);
            sgks_cmd_dump_mem_file_s *dump_mem = (sgks_cmd_dump_mem_file_s *)ioctl_msg.msg_data;
            sgks_mdi_ioc_DumpMemToFile(dump_mem->file_path, dump_mem->addr, dump_mem->len);

            ret = SGKS_SUCCESS;
            break;
        }

        case SGKS_MDI_OPERATION_SENDCMD:
        {
            if ( g_mdi_manager.dsp_status.op_mode != SGKS_DSP_DECODE_MODE)
            {
                sgks_mdi_cmd_lock();
            }

            ret = sgks_mdi_ioc_sendcmd(ioctl_msg.msg_data, ioctl_msg.msg_head.msg_size);

            if ( g_mdi_manager.dsp_status.op_mode != SGKS_DSP_DECODE_MODE)
            {
                sgks_mdi_cmd_unlock();
            }
			
            break;
        }

        case SGKS_MDI_OPERATION_OPT_D_CACHE:
        {
            CHECK_PARAM_SIZE("sgks_mdi_opt_d_cache_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_opt_d_cache_s),SGKS_FAIL);
            sgks_mdi_opt_d_cache_s *cache = (sgks_mdi_opt_d_cache_s*)ioctl_msg.msg_data;
            if(cache->start < PAGE_OFFSET)
            {
                ret = sgks_mdi_ioc_clean_cache(cache->cache_type, (cache->start), cache->size);
            }
            else
            {
                ret = sgks_mdi_ioc_clean_cache(cache->cache_type, sgks6802_phys_to_virt(cache->start), cache->size);
            }

            break;
        }

        case SGKS_MDI_OPERATION_SETMAINMPI:
        {
            CHECK_PARAM_SIZE("sgks_mdi_main_mpi_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_main_mpi_s),SGKS_FAIL);
            sgks_mdi_main_mpi_s *arg 				   = ioctl_msg.msg_data;
            g_mdi_manager.main_mpi.isp_CmdCallBack  = arg->isp_CmdCallBack;
            g_mdi_manager.main_mpi.isp_GetFrameTime = arg->isp_GetFrameTime;
            g_mdi_manager.main_mpi.isp_GetMpiState  = arg->isp_GetMpiState;
            g_mdi_manager.main_mpi.isp_MdiCallBack  = arg->isp_MdiCallBack;
            g_mdi_manager.main_mpi.isp_ConfigSensor = arg->isp_ConfigSensor;

            ret = SGKS_SUCCESS;
            break;
        }

        case SGKS_MDI_OPERATION_GETMAINMPI:
        {
            memset(ioctl_msg.msg_data, 0, sizeof(ioctl_msg.msg_data));
            sgks_mdi_main_mpi_s *arg 	= ioctl_msg.msg_data;
            *arg 						= g_mdi_manager.main_mpi;
            ret = SGKS_SUCCESS;
            break;
        }

        case SGKS_MDI_OPERATION_REG_WRITE:
        case SGKS_MDI_OPERATION_DEBUG_REGWRITE:
        {
            CHECK_PARAM_SIZE("sgks_mdi_reg_rw_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_reg_rw_s),SGKS_FAIL);
            sgks_mdi_reg_rw_s *reginfo = (sgks_mdi_reg_rw_s*)ioctl_msg.msg_data;
            unsigned long *reg_map     = NULL;
            int i = 0;



            for (i=0; i<reginfo->reg_num; i++)
            {

                if (reginfo->reg_info[i].addr_type == SGKS_MDI_REG_ADDR_TYPE_PHY)
                {
                    reg_map = (unsigned long *)ioremap(reginfo->reg_info[i].addr, 4);
                    *reg_map = (unsigned long)reginfo->reg_info[i].val;
                    iounmap(reginfo->reg_info[i].addr);
                    //printk("[write reg phy] reginfo->reg_info[i].addr 0x%x, reginfo->reg_info[i].val 0x%x\n",reginfo->reg_info[i].addr, reginfo->reg_info[i].val);
                }
                else if (reginfo->reg_info[i].addr_type == SGKS_MDI_REG_ADDR_TYPE_VIR)
                {
                    //printk("[write reg vir] reginfo->reg_info[i].addr 0x%x, reginfo->reg_info[i].val 0x%x\n",reginfo->reg_info[i].addr, reginfo->reg_info[i].val);
                    sgks_writel(reginfo->reg_info[i].addr, reginfo->reg_info[i].val);
                }
                else
                {
                    printk("reg write: addr type err\n");
                    err_count++;
                    break;
                }

                if (reginfo->reg_info[i].delay_ms > 0)
                {
                    mdelay(reginfo->reg_info[i].delay_ms);
                }


            }

            ret = (err_count == 0) ? SGKS_SUCCESS : SGKS_FAIL;

            break;
        }

        case SGKS_MDI_OPERATION_REG_READ:
        {
            CHECK_PARAM_SIZE("sgks_mdi_reg_rw_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_reg_rw_s),SGKS_FAIL);
            ret = sgks_mdi_ioc_read_reg((sgks_mdi_reg_rw_s*)ioctl_msg.msg_data, 1);
            break;
        }

        case SGKS_MDI_OPERATION_DECRYPT_MEM_DATA:
        {
            CHECK_PARAM_SIZE("sgks_mdi_decrpty_mem_data_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_decrpty_mem_data_s),SGKS_FAIL);
            sgks_mdi_decrpty_mem_data_s *decrpty = (sgks_mdi_decrpty_mem_data_s*)ioctl_msg.msg_data;

            int i = 0;
            long retval = 0;
            int32_t __iomem *base = (int32_t *)sgks6802_phys_to_virt(decrpty->phy_mem_addr);
            sgks_crypto_case_s crypto_case;
            crypto_case.mode = SGKS_CRYPTO_DES;
            memcpy(&crypto_case.pkey, &decrpty->pkey, sizeof(sgks_crypto_key_s));

			#if 0
			for (i = 0; i < 8; i++)
			printk("crypto_case.pkey.key 0x%x 0x%x\n",crypto_case.pkey.key[i],crypto_case.pkey.key);
			#endif

            for(i = 0; i < ((decrpty->size / 4)); i += 2)
            {
                crypto_case.source.data[0] = *(base + i);
                crypto_case.source.data[1] = *(base + i + 1);
                retval = sgks_mdi_crypto_ProcessData(&crypto_case, SGKS_CRYPTO_DECRPT);
                *(base + i) = crypto_case.dec_dest.data[0];
                *(base + i + 1) = crypto_case.dec_dest.data[1];
            }

			ret = SGKS_SUCCESS;

			//printk("SGKS_MDI_OPERATION_DECRYPT_MEM_DATA ok\n");

			break;

        }

        case SGKS_MDI_OPERATION_ADDR_CONV:
        {
            CHECK_PARAM_SIZE("sgks_mdi_memaddr_conv_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_memaddr_conv_s),SGKS_FAIL);

            int i = 0;
            sgks_mdi_memaddr_conv_s *memaddr = (sgks_mdi_memaddr_conv_s*)ioctl_msg.msg_data;

            for (i=0; i<memaddr->addr_num; i++)
            {
                if (memaddr->addr_info[i].type == 0)
                {
                    memaddr->addr_info[i].desc_addr = sgks6802_phys_to_virt(memaddr->addr_info[i].src_addr);
                }
                else if (memaddr->addr_info[i].type == 1)
                {
                    memaddr->addr_info[i].desc_addr = sgks6802_virt_to_phys(memaddr->addr_info[i].src_addr);
                }
                else
                {
                    printk("addr conv: type err\n");
                    err_count++;
                }
                printk("src [0x%x], desc [0x%x]\n",memaddr->addr_info[i].src_addr,memaddr->addr_info[i].desc_addr);
            }

            ret = (err_count == 0) ? SGKS_SUCCESS : SGKS_FAIL;
            copy_user = 1;
            break;
        }

        case SGKS_MDI_OPERATION_DEBUG_REGREAD:
        {
            CHECK_PARAM_SIZE("sgks_mdi_reg_rw_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_reg_rw_s),SGKS_FAIL);
            ret = sgks_mdi_ioc_read_reg((sgks_mdi_reg_rw_s*)ioctl_msg.msg_data, 1);
            break;
        }
        case SGKS_MDI_OPERATION_MALLOC:
        {
            CHECK_PARAM_SIZE("sgks_mdi_mem_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_mem_s),SGKS_FAIL);
            ret = sgks_mdi_ioc_malloc(filp, (sgks_mdi_mem_s*)ioctl_msg.msg_data);
            break;
        }
        case SGKS_MDI_OPERATION_FREE:
        {
            CHECK_PARAM_SIZE("sgks_mdi_mem_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_mem_s),SGKS_FAIL);
            ret = sgks_mdi_ioc_free(filp, (sgks_mdi_mem_s*)ioctl_msg.msg_data);
            break;
        }

        case SGKS_MDI_OPERATION_SETENCODE:
        {
            ret = sgks_mdi_ioc_SetEncode();
            break;
        }

        case SGKS_MDI_OPERATION_GET_SESSION_ID:
        {
            CHECK_PARAM_SIZE("sgks_mdi_session_s", ioctl_msg.msg_head.msg_size, sizeof(sgks_mdi_session_s), SGKS_FAIL);
            sgks_mdi_session_s *pSession = (sgks_mdi_session_s *)ioctl_msg.msg_data; 
            *(pSession->session) = g_stream_session_id[pSession->streamId][g_stream_session_index[pSession->streamId]] & 0xF;
            break;
        }
        
        case SGKS_MDI_OPERATION_CREATE_SESSION_ID:
        {
            CHECK_PARAM_SIZE("u32", ioctl_msg.msg_head.msg_size, sizeof(u32), SGKS_FAIL);
            int stream = *(int *)ioctl_msg.msg_data;
            create_session_id(stream);
            break;
        }
        
        case SGKS_MDI_OPERATION_READ_BITSTREAM:
        {
            CHECK_PARAM_SIZE("sgks_mdi_enc_bits_info", ioctl_msg.msg_head.msg_size, sizeof(sgks_mdi_enc_bits_info), SGKS_FAIL);
            sgks_mdi_enc_bits_info *pBitsInfo = (sgks_mdi_enc_bits_info *)ioctl_msg.msg_data;
            ret = sgks_mdi_encode_read_fifo(pBitsInfo);
            break;
        }

        case SGKS_MDI_OPERATION_GET_YUV_INFO:
        {
            CHECK_PARAM_SIZE("sgks_mdi_yuv_info_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_yuv_info_s),SGKS_FAIL);
			memset(ioctl_msg.msg_data, 0, sizeof(ioctl_msg.msg_data));
			
			ret = sgks_mdi_ioc_GetYuvData((sgks_mdi_yuv_info_s *)ioctl_msg.msg_data);
			
			break;
        }

        case SGKS_MDI_OPERATION_WAIT_COMPLETION:
        {
            CHECK_PARAM_SIZE("sgks_mdi_wait_completion_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_wait_completion_s),SGKS_FAIL);

            ret = sgks_mdi_ioc_WaitCompletion((sgks_mdi_wait_completion_s *)ioctl_msg.msg_data);
            break;
        }
        
        case SGKS_MDI_OPERATION_OSD_BIND_FB:
        {
            CHECK_PARAM_SIZE("sgks_mdi_osdVoInfoToFb_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_mdi_osdVoInfoToFb_s),SGKS_FAIL);
            ret = sgks_mdi_osd_register_to_framebuffer((sgks_mdi_osdVoInfoToFb_s *)ioctl_msg.msg_data);
            break;
        }

        case SGKS_MDI_OPERATION_WAIT_YUV_ENC_COMPLETE:
        {
            static int needwait = 0;
            CHECK_PARAM_SIZE("u32", ioctl_msg.msg_head.msg_size, sizeof(u32),SGKS_FAIL);
            if(needwait)
            {
                ret = sgks_mdi_ioc_WaitYuv2EncComplete(*(u32 *)ioctl_msg.msg_data);
            }
            else
            {
                needwait = 1;
                ret = SGKS_SUCCESS;
            }
            g_mdi_manager.dsp_compl.yuv_to_enc_compl_wait_count++;  
            break;
        }

        case SGKS_MDI_OPERATION_GET_YUV_ENC_JPEG_INFO:
        {
            unsigned long flags;
            atomic_inc(&g_mdi_manager.dsp_compl.wait_yuv_to_enc_sync_done);
            if(wait_for_completion_timeout(&g_mdi_manager.dsp_compl.yuv_to_enc_sync_cmpl, msecs_to_jiffies(100)) == 0)
            {
                DEBUGMSG(ZONE_ERROR, ("%s(%d): wait yuv_to_enc_sync_cmpl timeout\n", __func__, __LINE__));
                atomic_set(&g_mdi_manager.dsp_compl.wait_yuv_to_enc_sync_done, 0);    
                ret = SGKS_FAIL;
            }
            sgks_mdi_jpeg_info_s *pJpegInfo = (sgks_mdi_jpeg_info_s *)ioctl_msg.msg_data;
            local_irq_save(flags);
            memcpy(pJpegInfo, &g_mdi_manager.jpeg_info, sizeof(sgks_mdi_jpeg_info_s));
            local_irq_restore(flags);
            break;
        }
        
        default:
        {
            ret  = SGKS_OPERATION_ERR_ID;
            printk("mdi ioctl : oper id  err!\n");
            break;
        }

        }

        break;

    }


    default:
    {
        ret  = SGKS_OPERATION_ERR_ID;
        printk("mdi ioctl err!\n");
        break;
    }


    }

    ioctl_msg.msg_head.ack_flag = ret;

    //printk("-----end--------mdi ioctl 0x%x\n",ioctl_msg.msg_head.msg_type);

    //if (copy_user == 1)
    {
        if (copy_to_user((msg_t __user *)args, &ioctl_msg, sizeof(msg_t)) != 0)
        {

            return SGKS_OPERATION_ERR_SYS;
        }
    }



    return ret;

}



static int sgks_mdi_mmap(struct file *filp, struct vm_area_struct *vma)
{
    int ret = 0;

    sgks_mdi_mmap_s *mdi_mmap = &g_mdi_manager.user_area.user_mmap;

    //printk("sgks_mdi_mmap 0x%x\n",mdi_mmap->mmap_phy_start_addr);

    sgks_mdi_mmap_lock();

    if(remap_pfn_range(vma, vma->vm_start, (u32)mdi_mmap->mmap_phy_start_addr >> PAGE_SHIFT, mdi_mmap->mmap_phy_size, vma->vm_page_prot))
    {
        sgks_mdi_mmap_unlock();
        return -ENOMEM;
    }

    sgks_mdi_mmap_unlock();

    //printk("sgks_mdi_mmap end\n");

    return ret;

}


static int sgks_mdi_open(struct inode *inode, struct file *filp)
{
    g_mdi_manager.user_area.file = filp;
    filp->private_data               = &g_mdi_manager.user_area;
    return 0;
}


static int sgks_mdi_fasync(int fd, struct file *filp, int mode)
{

    return 0;
}

static int sgks_mdi_release(struct inode *inode, struct file *filp)
{
    return 0;
}

static struct file_operations sgks_mdi_fops =
{
    .owner = THIS_MODULE,
    .unlocked_ioctl = sgks_mdi_ioctl,
    .mmap = sgks_mdi_mmap,
    .open = sgks_mdi_open,
    .fasync = sgks_mdi_fasync,
    .release = sgks_mdi_release
};

static int __init sgks_mdi_delete_dev(int *major, int minor, int numdev, const char *name, struct cdev *cdev, struct file_operations *fops)
{
    dev_t dev_id;
    dev_id = MKDEV(*major, minor);
    unregister_chrdev_region(dev_id, numdev);
    kobject_del(&cdev->kobj);
    cdev_del(cdev);
    return 0;
}



static int __init sgks_mdi_create_dev(int *major, int minor, int numdev,const char *name, struct cdev *cdev, struct file_operations *fops)
{
    dev_t dev_id;
    int ret;
    struct cdev *sgks_mdi_dev = NULL;
    struct class *sgks_mdi_class;

    if(*major)
    {
        dev_id = MKDEV(*major, minor);
        ret = register_chrdev_region(dev_id, numdev, name);
    }
    else
    {
        ret = alloc_chrdev_region(&dev_id, 0, numdev, name);
        *major = MAJOR(dev_id);
    }

    if(ret)
    {
        printk("failed to get dev region for %s\n", name);
        return ret;
    }

    cdev_init(cdev, fops);
    cdev->owner = THIS_MODULE;
    ret = cdev_add(cdev, dev_id, 1);

    if(ret)
    {
        printk("cdev_add failed for %s, error = %d\n", name, ret);
        return ret;
    }

    printk("%s dev init done, dev_id = %d:%d\n", name, MAJOR(dev_id), MINOR(dev_id));


    /*create dev node*/

    sgks_mdi_class= class_create(THIS_MODULE, name);

    if (IS_ERR(sgks_mdi_class))
    {
        printk("class_create error\n" );
        return -1;
    }

    sgks_mdi_dev=device_create(sgks_mdi_class, NULL, MKDEV(*major, minor), NULL,name);
    if (sgks_mdi_dev == NULL)
    {
        printk("device_create error\n" );
        return -1;
    }


    return 0;
}

static void sgks_mdi_init_compl()
{

    init_completion(&g_mdi_manager.dsp_compl.dsp_readlog_compl);
    init_completion(&g_mdi_manager.dsp_compl.isp_statis_compl);
    init_completion(&g_mdi_manager.dsp_compl.cmd_avail_compl);
    init_completion(&g_mdi_manager.dsp_compl.decode_compl);
    init_completion(&g_mdi_manager.dsp_compl.state_change_compl);
    init_completion(&g_mdi_manager.dsp_compl.yuv_to_enc_compl);    
    init_completion(&g_mdi_manager.dsp_compl.yuv_to_enc_sync_cmpl); 
    atomic_set(&g_mdi_manager.dsp_compl.wait_yuv_to_enc_sync_done, 0);

}
/*****************framebuffer osd*****************************/
typedef union __argb8888
{
    unsigned int data32;
    struct __bit32s
    {
        unsigned int b: 8;
        unsigned int g: 8;
        unsigned int r: 8;
        unsigned int a: 8;
    } bits;
} argb8888_u;

typedef union __argb4444
{
    unsigned short data16;
    struct __bit16s
    {
        unsigned short b: 4;
        unsigned short g: 4;
        unsigned short r: 4;
        unsigned short a: 4;
    } bits;
} argb4444_u;

static int Argb8888ToAyuv4444Init(unsigned short *pLUT)
{
    unsigned int  index;
    unsigned char a, r, g, b;
    unsigned char  y, u, v;
    
    for(index = 0; index < (0x1 << 16); index++)
    {
        a = (index & 0xF000) >> 12;
        r = (index & 0x0F00) >> 4;
        g = (index & 0x00F0) >> 0;
        b = (index & 0x000F) << 4;
        y = ((66 * r + 129 * g +  25 * b + 128) >> 8)  + 16;
        u = ((-38 * r -  74 * g + 112 * b + 128) >> 8) + 128;
        v = ((112 * r -  94 * g -  18 * b + 128) >> 8) + 128;
        y >>= 4;
        u >>= 4;
        v >>= 4;
        pLUT[index] = ((a << 12) | (y << 8) | (u << 4) | (v << 0));
    }

    return 0;
}

static void Argb8888ConvertToAyuv4444(unsigned short *pLUT,
                                               unsigned int *pSrc, 
                                               unsigned short *pDst,
                                               unsigned int width,
                                               unsigned int height)
{
    u32 i;
    u32        pixel;
    argb8888_u argb8888;
    argb4444_u argb4444;

    pixel = width * height;

    for(i = 0; i < pixel; i++)
    {
        argb8888.data32 = pSrc[i];
        argb4444.bits.a = argb8888.bits.a >> 4;
        argb4444.bits.r = argb8888.bits.r >> 4;
        argb4444.bits.g = argb8888.bits.g >> 4;
        argb4444.bits.b = argb8888.bits.b >> 4;
        pDst[i] = pLUT[argb4444.data16];
    }
}

static int sgks_argb8888_2_ayuv4444_pan_display(struct fb_var_screeninfo *var,
        struct fb_info *info)
{
    static int sw = 0;
    u16 *pDstOSDBuffer = NULL;
    u32 *pSrcOSDBuffer = NULL;

    sw++;
    sw &= 0x01;

    //4 bytes per pixel
    pSrcOSDBuffer = (u32 *)(info->screen_base + info->fix.line_length * var->yoffset);
    //2 bytes per pixel
    pDstOSDBuffer = (u16 *)(g_mdi_manager.osd_voInfo.osd_data_buf_addr + sw * var->xres * var->yres * 2);

    Argb8888ConvertToAyuv4444(g_mdi_manager.osd_voInfo.osd_clut_addr,
                                pSrcOSDBuffer,
                                pDstOSDBuffer,
                                var->xres,
                                var->yres
                                );
    clean_d_cache(pDstOSDBuffer, var->xres * var->yres * 2);
    *(u32 *)g_mdi_manager.osd_voInfo.osd_info_buf_addr = virt_to_phys(pDstOSDBuffer);
    return 0;
}
static int sgks_fb_set_par(struct fb_info *info)
{
    return 0;
}
static int sgks_fb_set_cmap(struct fb_cmap *cmap, struct fb_info *info)
{
    return 0;
}
static int sgks_fb_set_blank(int blank_mode, struct fb_info *info)
{
    return 0;
}
static int sgks_mdi_osd_register_to_framebuffer(sgks_mdi_osdVoInfoToFb_s *info)
{
    struct sgks6802_platform_fb    *pplatform_info;
    struct sgks6802_fb_media_info  *pmedia_info;

    pplatform_info = kzalloc(sizeof(struct sgks6802_platform_fb), GFP_KERNEL);
    if(!pplatform_info)
    {
        printk("%s: Out of memory!\n", __func__);
        return SGKS_FAIL;
    }    
    pmedia_info = kzalloc(sizeof(struct sgks6802_fb_media_info), GFP_KERNEL);
    if(!pmedia_info)
    {
        printk("%s: Out of memory!\n", __func__);
        return SGKS_FAIL;
    }
    
    if(sgks6802_fb_get_platform_info(0, pplatform_info))
    {
        printk("get fb platform info error\n");
        return SGKS_FAIL;
    }
    
    if((pplatform_info->screen_var.xres != info->width)
        ||(pplatform_info->screen_var.yres != info->height))
    {
        printk("Error:xres:%d != osd width:%d, or yres:%d != osd height:%d", pplatform_info->screen_var.xres,
                pplatform_info->screen_var.yres,
                info->width,
                info->height);
        return SGKS_FAIL;
    }
        
    if(g_mdi_manager.osd_voInfo.osd_clut_addr == 0)
    {
        g_mdi_manager.osd_voInfo.osd_clut_addr = kmalloc((1<<16)*2, GFP_KERNEL);
        if(g_mdi_manager.osd_voInfo.osd_clut_addr == 0)
        {
            printk("%s(%d), out of memory\n", __func__, __LINE__);
            return SGKS_FAIL;
        }  
        
        g_mdi_manager.osd_voInfo.osd_data_buf_addr = kmalloc(info->width * info->width*2*2, GFP_KERNEL);
        if(g_mdi_manager.osd_voInfo.osd_data_buf_addr == 0)
        {
            printk("%s(%d), out of memory\n", __func__, __LINE__);
            return SGKS_FAIL;
        }   
        Argb8888ToAyuv4444Init((u16 *)g_mdi_manager.osd_voInfo.osd_clut_addr);
    }
    g_mdi_manager.osd_voInfo.osd_info_buf_addr =phys_to_virt(info->osd_buf_info_phy_addr);
    
    pmedia_info->screen_var = pplatform_info->screen_var;
    pmedia_info->screen_fix = pplatform_info->screen_fix;
    pmedia_info->dsp_status = SGKS_DSP_ENCODE_MODE;
    
    switch(pplatform_info->color_format)
    {
        case SGKS_FB_COLOR_ARGB8888:
        {
            pmedia_info->pan_display = sgks_argb8888_2_ayuv4444_pan_display;
            break;
        }
        default:
        {
            printk("not suport\n");
            return SGKS_FAIL;
        }
    }
    pmedia_info->set_par = sgks_fb_set_par;
    pmedia_info->setcmap = sgks_fb_set_cmap;
    pmedia_info->set_blank = sgks_fb_set_blank;                           
    sgks6802_fb_set_media_info(0, pmedia_info);
    return 0;
}


static void __exit sgks_mdi_exit(void)
{
    sgks_mdi_delete_dev(&sgks_mdi_major, sgks_mdi_minor, 1, sgks_mdi_name, &sgks_mdi_cdev, &sgks_mdi_fops);
}


static int __init sgks_mdi_init(void)
{
    int ret;

	printk("**********************************************************************\n");
	printk("* sgks mpi mdi svn version: %s  build time: %s  \r\n",SVNREVISION,TIMESTAMP);
	printk("**********************************************************************\n");

    memset(&g_mdi_manager, 0, sizeof(sgks_mdi_manager_s));
    g_mdi_manager.dsp_status.op_mode = DSP_UNKNOWN_MODE;
    g_mdi_manager.dsp_status.op_sub_mode = DSP_ENC_UNKNOWN_MODE;
    g_mdi_manager.dsp_status.state = ENC_UNKNOWN_STATE;

    // the /dev/sgks_video device
    if((ret = sgks_mdi_create_dev(&sgks_mdi_major, sgks_mdi_minor, 1,sgks_mdi_name, &sgks_mdi_cdev, &sgks_mdi_fops)) < 0)
    {
        return -1;
    }


    sgks_mdi_init_compl();


    return 0;

Fail:
    sgks_mdi_exit();
    return ret;
}








module_init(sgks_mdi_init);
module_exit(sgks_mdi_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("SGKS MICROELECTRONICS Inc.");
MODULE_DESCRIPTION("sgks mdi Driver");







